题目:
http://codevs.cn/problem/1961/
思路:
明确:我们需要把所有能更新到的答案都更新出来;
因为:大的不一定差,因为它可以加一个小的值再%60变得更小;小的不一定好,因为可能有更小的存在;
所以,这个题并不是最短路;
考虑到有时间这个状态,我们可以bfs
总结:
1.明确图论算法的适用范围;
2.bfs暴搜最万能!
3.注意状态的表示;
4.坑的地方在于,本题存在极小值;
由于取模后必须保证时间为小于60的正整数,所以需要不断加60直到>0,以后遇到取模的题,一定要加;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN=200001,inf=2147483647;
int fst[MAXN],nxt[MAXN],dis[MAXN],fa[MAXN];
int tot,n,m;
bool vis[MAXN],can[8001][61];
struct hh{int from,to,cost;}ma[MAXN];
struct sh{int num,ti;}ss[MAXN];
void build(int f,int t,int c)
{
ma[++tot]=(hh){f,t,c};
nxt[tot]=fst[f];
fst[f]=tot;
return;
}
int find(int x)
{
int r=x,t;
while(r!=fa[r]) r=fa[r];
while(x!=t) t=fa[x],fa[x]=r,x=t;
return r;
}
void bfs()
{
queue<sh>q;
q.push((sh){1,0}),can[1][0]=1;
while(!q.empty())
{
sh x=q.front();
q.pop();
for(int i=fst[x.num];i;i=nxt[i])
{
int v=ma[i].to;
int cc=(x.ti+ma[i].cost)%60;
while(cc<0) cc+=60;
if(!can[v][cc]) can[v][cc]=1,q.push((sh){v,cc});
}
}
return;
}
void solve()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(find(x)!=find(y)) fa[find(x)]=find(y);
build(x,y,z);
build(y,x,z);
}
if(find(1)!=find(2)) {cout<<"60";return;}
bfs();
for(int i=0;i<=59;i++)
if(can[2][i])
{
if(i<10) cout<<"0";
cout<<i;
break;
}
return;
}
int main()
{
solve();
return 0;
}