hdu 1317+hdu 1535(SPFA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1317
思路:只要在SPFA中将一个条件,就不会进入负环。那么如果有正环呢,显然退出条件是某个点入队列次数>=n,此时退出时只需判断当前点是否与n存在路径,这步可以用Floyd来实现。。。
View Code
1 #include<iostream> 2 #include<queue> 3 const int MAXN=110; 4 using namespace std; 5 int n; 6 int weight[MAXN]; 7 int power[MAXN]; 8 int _count[MAXN];//记录某点的入队列次数 9 bool map[MAXN][MAXN]; 10 bool reach[MAXN][MAXN];//floyd判断任何两点是否可达 11 12 13 void Floyd(){ 14 for(int k=1;k<=n;k++){ 15 for(int i=1;i<=n;i++){ 16 for(int j=1;j<=n;j++){ 17 reach[i][j]=(reach[i][j] 18 ||(reach[i][k]&&reach[k][j])); 19 } 20 } 21 } 22 } 23 24 bool SPFA(int now){ 25 queue<int>Q; 26 Q.push(now); 27 memset(power,0,sizeof(power)); 28 memset(_count,0,sizeof(_count)); 29 power[1]=100; 30 while(!Q.empty()){ 31 int now=Q.front(); 32 Q.pop(); 33 _count[now]++; 34 if(_count[now]>=n)return reach[now][n];//如果某个点的次数超过n次,那么说明存在正环,此时只要判断这点到n点是否可达就行了 35 for(int next=1;next<=n;next++){ 36 if(map[now][next]&&power[now]+weight[next]>power[next] 37 &&power[now]+weight[next]>0){ 38 Q.push(next); 39 power[next]=power[now]+weight[next]; 40 } 41 } 42 } 43 return power[n]>0; 44 } 45 46 int main(){ 47 while(~scanf("%d",&n)&&n!=-1){ 48 memset(map,false,sizeof(map)); 49 memset(reach,false,sizeof(reach)); 50 for(int i=1;i<=n;i++){ 51 int num; 52 scanf("%d%d",&weight[i],&num); 53 for(int j=1;j<=num;j++){ 54 int k; 55 scanf("%d",&k); 56 map[i][k]=true; 57 reach[i][k]=true; 58 } 59 } 60 Floyd(); 61 if(!reach[1][n]){ 62 printf("hopeless\n"); 63 }else { 64 if(SPFA(1)){ 65 printf("winnable\n"); 66 }else 67 printf("hopeless\n"); 68 } 69 } 70 return 0; 71 }
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1535
思路:正向建一次图,反向建一次图,然后两次SPFA就可以了,采用vector的邻接表形式,特别好用。。。
View Code
1 #include<iostream> 2 #include<vector> 3 #include<queue> 4 const int MAXN=1000000+10; 5 typedef long long ll; 6 const ll inf=1e60; 7 using namespace std; 8 struct Node{ 9 int v,w; 10 }; 11 vector<Node>mp1[MAXN];//正向建图 12 vector<Node>mp2[MAXN];//反向建图 13 int n,m; 14 ll cost[MAXN]; 15 16 void SPFA(int u,vector<Node>mp[]){ 17 for(int i=2;i<=n;i++)cost[i]=inf; 18 cost[1]=0; 19 queue<int>Q; 20 Q.push(u); 21 while(!Q.empty()){ 22 int u=Q.front(); 23 Q.pop(); 24 for(int i=0;i<mp[u].size();i++){ 25 int v=mp[u][i].v; 26 int w=mp[u][i].w; 27 if(cost[v]>cost[u]+w){ 28 cost[v]=cost[u]+w; 29 Q.push(v); 30 } 31 } 32 } 33 } 34 35 36 int main(){ 37 int _case; 38 scanf("%d",&_case); 39 while(_case--){ 40 scanf("%d%d",&n,&m); 41 for(int i=1;i<=n;i++){ 42 mp1[i].clear(); 43 mp2[i].clear(); 44 } 45 for(int i=1;i<=m;i++){ 46 int u,v,w; 47 scanf("%d%d%d",&u,&v,&w); 48 Node p1,p2; 49 p1.v=u,p2.v=v,p1.w=p2.w=w; 50 mp1[u].push_back(p2); 51 mp2[v].push_back(p1); 52 } 53 SPFA(1,mp1);//正向求一次 54 ll ans=0; 55 for(int i=2;i<=n;i++){ 56 ans+=cost[i]; 57 } 58 SPFA(1,mp2);//反向求一次 59 for(int i=2;i<=n;i++){ 60 ans+=cost[i]; 61 } 62 printf("%lld\n",ans); 63 } 64 return 0; 65 } 66 67