poj2240_类似负权回路
题意:给出一些不同类型的货币和货币之间兑换的比例,求能否实现从一种硬币开始到自身结束后,实现盈利
分析:
1.一开始遇到这个题的时候,我首先想到的是dfs,在遍历的过程中如果遇到环的话进行判断,得出结果。但是这样考虑是不正确的。比如:
A 1.0 B
B 1.0 C
B 5.0 D
C 0.1 D
D 1.0 A
dfs时,如果先搜ABCDA是不成功的,如果这时标记搜过的D为舍弃,则ABDA就搜不到了。
2.放弃dfs后,发现这里的思路跟寻找负权回路很相似,寻找负权回路是因为在执行过程中可以不断更新,而这里如果存在盈利的话,也可以不断更新。
使用bellman-ford,必须保证图中每个点为起始点都没有回路。而使用spfa,只要看入队列次数就行
代码:
bellman-ford
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <memory.h> 4 #define white 0 5 #define black 1 6 using namespace std; 7 //192K 32MS 8 //bellman-ford 9 10 const int maxp=31; 11 const int maxe=1000; 12 struct edge 13 { 14 int v; 15 double w; 16 int next; 17 }edge[maxe]; 18 19 typedef struct 20 { 21 double value; 22 int color; 23 int pre; 24 }pp; 25 pp point[maxp]; 26 int p,e; 27 bool flag; 28 29 void bellman_ford(int u) 30 { 31 point[u].value=1.0; 32 point[u].color=black; 33 bool f; 34 int i,j,k; 35 for(k=1;k<=p-1;k++) 36 { 37 f=false; 38 for(i=1;i<=p;i++) 39 for(j=point[i].pre;j!=-1;j=edge[j].next) 40 { 41 int v=edge[j].v; 42 point[v].color=black; 43 double w=edge[j].w; 44 if(point[v].value<point[i].value*w) 45 { 46 point[v].value=point[i].value*w; 47 f=true; 48 } 49 } 50 if(!f) 51 break; 52 } 53 for(i=1;i<=p;i++) 54 for(j=point[i].pre;j!=-1;j=edge[j].next) 55 if(point[edge[j].v].value<point[i].value*edge[j].w) 56 { 57 flag=false; 58 return ; 59 } 60 flag=true; 61 } 62 63 struct mode 64 { 65 int pp; 66 char string[30]; 67 }mode[maxp]; 68 69 int find_point(char str[]) 70 { 71 int i; 72 for(i=1;i<=p;i++) 73 if(strcmp(mode[i].string,str)==0) 74 return mode[i].pp; 75 } 76 77 int main() 78 { 79 int i; 80 char name[30],names[30]; 81 double t; 82 int k=0; 83 while(scanf("%d",&p)&& p) 84 { 85 k++; 86 for(i=1;i<=p;i++) 87 { 88 scanf("%s",mode[i].string); 89 mode[i].pp=i; 90 point[i].pre=-1; 91 point[i].color=white; 92 point[i].value=-1.0; 93 } 94 95 scanf("%d",&e); 96 int index=1; 97 for(i=1;i<=e;i++) 98 { 99 scanf("%s%lf%s",name,&t,names); 100 int s=find_point(name); 101 int e=find_point(names); 102 edge[index].v=e; 103 edge[index].w=t; 104 edge[index].next=point[s].pre; 105 point[s].pre=index; 106 index++; 107 } 108 109 flag=true; 110 for(i=1;i<=p;i++) 111 { 112 if(!flag) 113 break; 114 if(point[i].color==white) 115 bellman_ford(i); 116 } 117 118 119 if(!flag) 120 printf("Case %d: Yes\n",k); 121 else 122 printf("Case %d: No\n",k); 123 } 124 return 0; 125 } 126 127 /* 128 3 129 USDollar 130 BritishPound 131 FrenchFranc 132 3 133 USDollar 0.5 BritishPound 134 BritishPound 10.0 FrenchFranc 135 FrenchFranc 0.21 USDollar 136 137 3 138 USDollar 139 BritishPound 140 FrenchFranc 141 6 142 USDollar 0.5 BritishPound 143 USDollar 4.9 FrenchFranc 144 BritishPound 10.0 FrenchFranc 145 BritishPound 1.99 USDollar 146 FrenchFranc 0.09 BritishPound 147 FrenchFranc 0.19 USDollar 148 149 0 150 */
spfa
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <memory.h> 4 #include <queue> 5 #define white 0 6 #define black 1 7 using namespace std; 8 //204K 32MS 9 10 const int maxp=31; 11 const int maxe=1000; 12 struct edge 13 { 14 int v; 15 double w; 16 int next; 17 }edge[maxe]; 18 19 typedef struct 20 { 21 double value; 22 int color; 23 int pre; 24 }pp; 25 pp point[maxp]; 26 int p,e; 27 bool flag; 28 int cnt[maxp]; 29 30 struct mode 31 { 32 int pp; 33 char string[30]; 34 }mode[maxp]; 35 36 int find_point(char str[]) 37 { 38 int i; 39 for(i=1;i<=p;i++) 40 if(strcmp(mode[i].string,str)==0) 41 return mode[i].pp; 42 } 43 44 void spfa(int u) 45 { 46 memset(cnt,0,sizeof(cnt)); 47 queue<int> q; 48 int t,i; 49 q.push(u); 50 point[u].color=black; 51 point[u].value=1.0; 52 cnt[u]++; 53 while(!q.empty()) 54 { 55 t=q.front(); 56 q.pop(); 57 point[t].color=white; 58 for(i=point[t].pre;i!=-1;i=edge[i].next) 59 { 60 int v=edge[i].v; 61 double w=edge[i].w; 62 if(point[v].value<point[t].value*w) 63 { 64 point[v].value=point[t].value*w; 65 if(point[v].color==white) 66 { 67 q.push(v); 68 point[v].color=black; 69 cnt[v]++; 70 if(cnt[v]>p) 71 { 72 flag=false; 73 return ; 74 } 75 } 76 } 77 } 78 } 79 } 80 81 int main() 82 { 83 int i; 84 char name[30],names[30]; 85 double t; 86 int k=0; 87 while(scanf("%d",&p)&& p) 88 { 89 k++; 90 for(i=1;i<=p;i++) 91 { 92 scanf("%s",mode[i].string); 93 mode[i].pp=i; 94 point[i].pre=-1; 95 point[i].color=white; 96 point[i].value=-1.0; 97 } 98 99 scanf("%d",&e); 100 int index=1; 101 for(i=1;i<=e;i++) 102 { 103 scanf("%s%lf%s",name,&t,names); 104 int s=find_point(name); 105 int e=find_point(names); 106 edge[index].v=e; 107 edge[index].w=t; 108 edge[index].next=point[s].pre; 109 point[s].pre=index; 110 index++; 111 } 112 113 flag=true; 114 spfa(1); 115 116 if(!flag) 117 printf("Case %d: Yes\n",k); 118 else 119 printf("Case %d: No\n",k); 120 } 121 return 0; 122 } 123 /* 124 3 125 USDollar 126 BritishPound 127 FrenchFranc 128 3 129 USDollar 0.5 BritishPound 130 BritishPound 10.0 FrenchFranc 131 FrenchFranc 0.21 USDollar 132 133 3 134 USDollar 135 BritishPound 136 FrenchFranc 137 6 138 USDollar 0.5 BritishPound 139 USDollar 4.9 FrenchFranc 140 BritishPound 10.0 FrenchFranc 141 BritishPound 1.99 USDollar 142 FrenchFranc 0.09 BritishPound 143 FrenchFranc 0.19 USDollar 144 145 0 146 */
这个题还可以用floyd做,因为没有确定的源点,最终求出arrray[i][i],如果大于初始值1,则yes,否则no
tjuoj 1129