T1:地铁巡查
思路:最小生成树
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=10000+10,INF=2147483647;
long long n,m,k,cnt,zr[maxn],nex[maxn],beg[maxn],to[maxn],c[maxn],v[maxn],s=1,minn=INF,sum,ans;
void add(long long x,long long y,int val){
zr[++cnt]=x;
nex[cnt]=beg[x];
beg[x]=cnt;
to[cnt]=y;
c[cnt]=val;
if(x==k||y==k)
c[cnt]=0;
}
void dfs(int p){
v[p]=1;
for(int i=beg[p];i;i=nex[i])
if(!v[to[i]])
dfs(to[i]);
}
int main(){
freopen("subway.in","r",stdin);
freopen("subway.out","w",stdout);
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=1;i<=m;i++){
long long a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
dfs(1);
for(int i=1;i<=n;i++)
if(!v[i]){
printf("No solution!");
return 0;
}
v[1]=1;
for(int i=1;i<n;i++){
minn=INF;
for(int j=1;j<=cnt;j+=2)
if(v[zr[j]]&&!v[to[j]]){
minn=c[j];
s=to[j];
}
sum+=minn;
v[s]=1;
}
printf("%lld",ans);
return 0;
}
经验:1.一定要将题意理解清楚
· 2.要备好各个模板。
T3:探险
思路:这道题我首先算出每个点与之相联系(包括自己)的点的个数,在尝试用这些数凑成n的倍数即可
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=40;
long long n,a[maxn][maxn],pd[maxn][maxn],sum[maxn],flag,vis[maxn],gs;
void pd1(long long y,long long sum1,long long times){
if(times>gs)
return ;
else if(times==gs&&sum1%n==0){
flag=1;
return ;
}
else
for(int i=1;i<=n;i++)
if(vis[i]==0&&i!=y){
vis[i]=1;
pd1(i,sum1+sum[i],times+1);
}
return ;
}
int main(){
freopen("adventure.in","r",stdin);
freopen("adventure.out","w",stdout);
scanf("%lld",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
scanf("%lld",&a[i][j]);
if(a[i][j]==1)
pd[i][j]=pd[j][i]=1;
}
for(int i=1;i<=n;i++){
sum[i]=1;
for(int j=1;j<=n;j++)
if(i!=j)
if(pd[i][j]||pd[j][i])
sum[i]++;
}
while(1){
memset(vis,0,sizeof(vis));
flag=0;
gs++;
for(int i=1;i<=n;i++)
pd1(i,sum[i],1);
if(flag==1){
printf("%lld",gs);
return 0;
}
}
return 0;
}
/*
5
0 1 1 0 0
1 0 0 1 1
1 0 0 1 1
0 1 1 0 0
0 1 1 0 0
3
5
0 1 1 0 1
1 0 0 0 1
1 0 0 1 1
0 0 1 0 1
1 1 1 1 0
1
*/
错因:没考虑到如果始终凑不成就会不断循环
教训:1.对于题目意思一定要理解清楚
2.要严格检查有没有遗漏或误解题目中的条件
3.一定要开longlong(考试时开了,给自己一个警告)
4.一定要手推样例!!!
5.特殊情况下,一些恰当的数学分析可以帮助你