標籤:
Bellman_ford:
用途:錢幣的互換,尋找最小正權環,即一圈後能回到自己並且比自己大或者小,如果是大,d數組就開0,否則開inf
適用條件:從源點到它的所有節點
步驟:1.開一個d數組,以d[s]記錄初始值 2.n-1次鬆弛 3.判斷每一個條件下是否盈利 4.如果每一個結點都盈利說明成功,否則說明存在負權環
模板:(main函數可忽略~只是為了方便瞭解各個參數如何得到)
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct edge{ int u; int v; int rate;}a[300];int s;int d[300];int n,m;bool bellman_ford(int s){ for(int i = 1; i <= n ;i++) d[i] = 0; d[s] = 1;//第s種為單位1 for(int i = 1; i <= n - 1 ; i++){//鬆弛n-1次,單純迴圈 int flag = 1; for(int j = 1; j <= m ; j++){//一共就這麼多交易規則 if(d[a[j].v] < d[a[j].u]*a[j].rate){//如果盈利那麼更新 flag = 0; d[a[j].v] = d[a[j].u]*a[j].rate; } } if(flag) return true;//如果對於每一個交易規則,a[d[j].v]一直等於d[a[j].u]*d[j].rate,說明沒有負環的存在,如果僅僅存在一個在接下來的交易中會把負環的介面補上 } return false;//如果仍舊這樣,說明存在了負環補不上,使得d[a[j].v]又減小了。}int main(){ char temp[300][300]; char temp1[300],temp2[300]; scanf("%d",&n);//一共n種貨幣 for(int i = 1; i <= n ; i++) scanf("%s",temp[i]); scanf("%d",&m);//一共m種交易情況 for(int i = 1; i <= m ; i++){ scanf("%s%s%d",&temp1[i],&temp2[i],&a[i].rate); for(int j = 1; j <= n; j++){ if(strcmp(temp[j],temp1) == 0) a[i].u = j; if(strcmp(temp[j],temp2) == 0) a[i].v = j; } } int flag1 = 0; for(int i = 1; i <= n ; i++)//任意一種錢出發 if(bellman_ford(i)==0){ flag1 = 1; printf("NO\n"); } if(!flag1) printf("YES\n"); return 0;}
演算法總結——bellman_ford