ACM+算法集--常用ACM算法

圖算法
 kurXX最小生成樹
 #include <iostream>
 #include <math.h>
 #include <algorithm>
 using namespace std;
 #define M 501
 #define LIM 20000000
 
 struct edg{
     int u,v;
     int w;
 }all_e[M*M/2];
 bool operator < (const edg &a,const edg &b){
     return a.w<b.w;
 }
 int set[M];
 
 inline bool uni(int set[],int a,int b){ 
     int ac=0,a2=a,b2=b,bc=0;
     while(set[a]!=0) {a=set[a];ac++;}
     if(a2!=a) set[a2]=a;
     while(set[b]!=0) {b=set[b];bc++;}
     if(b2!=b) set[b2]=b;  
     if(a==b) return false;
     if(ac<bc) set[a]=b;
     else set[b]=a;
     return true;
 }
 int main(){
     int i,j,k,n,m,u,v,t;
     cin >> t;
     for(k=0;k<t;k++){
     memset(set,0,sizeof(set));
     cin >> n;
     int ei=0;
     for(i=1;i<=n;i++){
         for(j=1;j<=n;j++){
             if(t!=0){
                 edg e;
                 e.u=i;e.v=j;
                 scanf("%d",&e.w);
                 if(i<j)
                     all_e[ei++]=e;
             }
         }
     }
     sort(&all_e[0],&all_e[ei]);
     int count=0;
     int size=ei;
     int max=0;
     for(i=0;i<size && count < n-1;i++){
         if(uni(set,all_e[i].u,all_e[i].v)){
             count++;
             if(all_e[i].w>all_e[max].w) max=i;
         }
     }
     printf("%d\n",all_e[max].w);
     }
     return 0;
 }
 Prim
 #include <iostream>
 using namespace std;
 #define M 2001
 
 int set[M]={0},g[M][M];
 char str[M][8];
 
 inline void make_map(int n,int g[M][M]){
     int i,j,k;
     for(i=1;i<=n;i++){
         for(j=i+1;j<=n;j++){
             int c=0;
             for(k=0;k<7;k++)
                 if(str[i][k]!=str[j][k]) c++;
             g[i][j]=g[j][i]=c;
         }
     }
 }
 
 int main(){
     int n,q[M],qf=0,ql=0,d[M],u;
     char c;
     scanf("%d%c",&n,&c);
     int i;
     while(n!=0){
         memset(set,0,sizeof(set)); memset(g,0,sizeof(g));
         for(i=1;i<=n;i++) {
             scanf("%s",&str[i]);
             q[i-1]=i;
             d[i]=2000000;
         }
         qf=0;ql=n-1;
         make_map(n,g);
         int sum=0;
         int f=false;
         while(qf<=ql){
             int min=qf;
             for(i=qf+1;i<=ql;i++){
                 if(d[q[i]] < d[q[min]]) min=i;
             }
             swap(q[qf],q[min]);
             u=q[qf]; qf++;
             if(f) sum+=d[u];
             for(i=1;i<=n;i++){
                 if(g[u][i] !=0 && g[u][i] < d[i]) d[i]=g[u][i];
             }
             f=true;
         }
         printf("The highest possible quality is 1/%d.\n",sum);
         scanf("%d%c",&n,&c);
     }
     return 0;
 }
 堆實現最短路
 #include <iostream>
 #include <string>
 #include <stdlib.h>
 #include <vector>;
 using namespace std;
 #define M 1001
 #define LIM 2000000000
 
 struct dd{ //最短距離
     int w,q;//w是距離值,q是堆中的相對位置
 }d[M],d2[M];
 struct node{
     int v,w;
 };
 int h[M],hs;
 vector<node> g[M],g2[M];
 void change_key(dd d[M],int v,int w){
     d[v].w=w;
     int i=d[v].q;
     while(i>1 && d[h[i/2]].w>d[h[i]].w){
         swap(h[i],h[i/2]);
         swap(d[h[i]].q,d[h[i/2]].q);
         i=i/2;
     }
 }
 inline void min_heaphy(dd d[M],int *a,int i,int s){//s 爲堆大小
     int l=i*2,r=i*2+1;
     int miner=i;
     if (l<=s && d[a[i]].w>d[a[l]].w)
         miner = l;
     else miner=i;
     if (r<=s && d[a[miner]].w>d[a[r]].w)
         miner=r;
     if(miner!=i){
         swap(a[i],a[miner]);
         swap(d[a[i]].q,d[a[miner]].q);
         min_heaphy(d,a,miner,s);
     }
 }
 inline void init(dd d[M],int n,int s){  //初始化圖和堆
     int i;
     hs=n;
     for(i=1;i<=n;i++){d[i].w=LIM;h[i]=d[i].q=i;}
     change_key(d,s,0);
 }
 inline void relax(dd d[M],int u,int v,int duv){
     if(d[v].w>d[u].w+duv) change_key(d,v,d[u].w+duv);
 }
 void dijkstra(vector<node> g[M],dd d[M],int n,int s){ //n is |V| && s is the source
     init(d,n,s);
     int i;
     while(hs!=0){
         int u=h[1];
         swap(h[1],h[hs]);
         swap(d[h[1]].q,d[h[hs]].q);
         hs--;
         min_heaphy(d,h,1,hs);
         for(i=0;i<g[u].size();i++) relax(d,u,g[u][i].v,g[u][i].w);
     }
 }
 最短路DIJ普通版
 #define M 101
 #define LIM 20000000
 
 int g[M][M],d[M],fd[2][M][M],gt[M][M],set[M];
 inline void init(int d[M],int n,int s){  //初始化圖
     int i;
     for(i=1;i<=n;i++)    d[i]=LIM;
     d[s]=0;
 }
 
 inline void relax(int d[M],int u,int v,int duv){
     if(d[v]>d[u]+duv)    d[v]=d[u]+duv;
 }
 void dijkstra(int g[M][M],int d[M],int n,int s){ //n is |V| && s is the source
     init(d,n,s);
     int q[M],ql=1,qf=1; //隊列
     int i;
     for(i=1;i<=n;i++) q[ql++]=i;
     while(qf!=ql){
         int min=qf;
         for(i=qf;i<ql;i++) if(d[q[i]]<d[q[min]]) min=i; 
         swap(q[qf],q[min]); //q[qf] is the min
         int u=q[qf++];
         for(i=1;i<=n;i++){
             if(g[u][i]!=0) relax(d,u,i,g[u][i]);
         }
     }
 }
 floyd
 #include <iostream>
 #include <vector>
 using namespace std;
 #define M 301
 #define LIM 200000000
 int w[M][M],d[2][M][M];
 
 void floyd(int g[M][M],int d[2][M][M],int n){
     int i,j,k;
     for(i=1;i<=n;i++){
         for(j=1;j<=n;j++){
             d[0][i][j]=g[i][j];
         }
         d[0][i][i]=0;
     }        //這裏是令d[0]=g
     for(k=1;k<=n;k++){
         for(i=1;i<=n;i++)
             for(j=1;j<=n;j++){
                 int t1=k%2; int t2=(t1+1)%2;
                 d[t1][i][j]=d[t2][i][j] < d[t2][i][k]+d[t2][k][j]?d[t2][i][j]:d[t2][i][k]+d[t2][k][j];
             }
     }
 }
 BELL_MAN
 inline void init(int d[M],int n,int s){  //初始化圖
     int i;
     for(i=1;i<=n;i++)    d[i]=2000000000;
     d[s]=0;
 }
 
 inline void relax(int d[M],int u,int v,int duv){
     if(d[v]>d[u]+duv)    d[v]=d[u]+duv;
 }
 
 void bell_man(int g[M][M],int d[M],int n,int s){ //n個結點 s爲源點
     int i,j,k;
     init(d,n,s);
     for(k=1;k<n;k++){
         for(i=1;i<=n;i++)
             for(j=1;j<=n;j++){
                 if(g[i][j]!=0) relax(d,i,j,g[i][j]);
             }
     }
 }
 拓撲排序
 #include <iostream>
 #include <stack>
 #include <vector>
 #include <list>
 using namespace std;
 vector <int> order;
 void find_id(list<int> g[],int id[],int n){  //尋找入度,沒有使用
     int i;
     list<int>::iterator k;
     for(i=0;i<n;i++){
         for(k=g[i].begin();k!=g[i].end();k++){
             id[*k]++;
         }
     }
 }
 void topo(list<int> g[],int id[],int n,bool &OK,bool &incon){//OK==false 表示未確定順序 incon==true 表示發現矛盾
     stack<int> s;
     order.erase(order.begin(),order.end());
     int t[26];
     copy(&id[0],&id[n],&t[0]);
     int i;
     for(i=0;i<n;i++){
         if(id[i]==0) 
             s.push(i);
     }
     if(s.size()!=1) OK=false;
     int count=0;
     while(!s.empty()){
         int v=s.top(); s.pop(); count++;
         order.push_back(v);
         list<int>::iterator k;
         for(k=g[v].begin();k!=g[v].end();k++){
             id[*k]--;
             if(id[*k]==0) s.push(*k);
             if(s.size()>1) OK=false;
         }
     }
     if(order.size() < n) OK=false;   //矛盾發生,會導致這種情況,小心
     if(count < n) incon=true;
     copy(&t[0],&t[n],&id[0]);
 }
 DFS強連通分支
 #include <iostream>
 #include <algorithm>
 #include <vector>
 using namespace std;
 #define M 20005
 vector<int> g[M],gt[M];
 bool used[M];
 int ft[M],sort_v[M],tim;
 bool comp(const int &u,const int &v){
     return ft[u]>ft[v];
 }
 inline int findp(int set[],int n){
     int n2=n;
     while(set[n]!=0) n=set[n];
     if(n2!=n) set[n2]=n;
     return n;
 }
 inline bool uni(int set[],int a,int b){ 
     int ac=0,a2=a,b2=b,bc=0,t;
     while(set[a]!=0) {a=set[a];ac++;}
     while(a2!=a) {t=set[a2]; set[a2]=a; a2=t;};
     while(set[b]!=0) {b=set[b];bc++;}
     while(b2!=b) {t=set[b2]; set[b2]=b; b2=t;}; 
     if(a==b) return false;
     if(ac<bc) set[a]=b;
     else set[b]=a;
     return true;
 }
 void dfs(vector<int> g[M],int u){
     if(used[u]) return;
     tim++;
     used[u]=true;
     int i;
     for(i=0;i<g[u].size();i++){
         dfs(g,g[u][i]);
     }
     tim++;
     ft[u]=tim;
     return;
 }
 void dfs2(vector<int> g[],int u,int r,int set[]){
     if(used[u]) return;
     uni(set,u,r);
     used[u]=true;
     int i;
     for(i=0;i<g[u].size();i++){
         dfs2(g,g[u][i],u,set);
     }
     return;
 }
 void scc(int n,vector<int> g[M],int set[]){
     int i,j;
     tim=0;
     memset(used,0,sizeof(used));
     memset(set,0,sizeof(set));
     for(i=1;i<=n;i++) sort_v[i]=i;
     for(i=1;i<=n;i++) if(!used[i]) dfs(g,i); //compute finishing times
     sort(&sort_v[1],&sort_v[n+1],comp); //decreasing f[u] order
     memset(used,0,sizeof(used));  
     for(i=1;i<=n;i++) for(j=0;j<g[i].size();j++) gt[g[i][j]].push_back(i); //compute gt
     for(i=1;i<=n;i++) if(!used[sort_v[i]]) dfs2(gt,sort_v[i],sort_v[i],set);  //make the scc
 }
 int main(){
     int i,j,n,m,u,v,set[M];
     cin >> n >> m;
     for(i=0;i<m;i++){
         scanf("%d%d",&u,&v);
         g[u].push_back(v);
     }
     scc(n,g,set);
     int pi=1,ptosc[M];
     struct Scc{
         int p,n;
     }sc[M];
     memset(sc,0,sizeof(sc));
     for(i=1;i<=n;i++){
         int p=findp(set,i);
         if(sc[p].p==0) {sc[p].p=pi; ptosc[pi++]=p;}
         sc[p].n++;
     }
     int n2=pi-1,od[M];
     memset(od,0,sizeof(od));
     for(i=1;i<=n;i++){
         for(j=0;j<g[i].size();j++){
             u=findp(set,i); v=findp(set,g[i][j]);
             if(sc[u].p!=sc[v].p) od[sc[u].p]++;
         }
     }
     int sum=0,s1=0;
     for(i=1;i<=n2;i++) if(od[i]==0) {s1++; sum+=sc[ptosc[i]].n;}
     if(s1!=1) sum=0;
     cout << sum << endl;
 }
 最大匹配
 #include <iostream>
 #include <string>
 #include <math.h>
 using namespace std;
 #define M 1001
 
 int n,m,match[M],ans[M];
 bool visit[M],g[M][M];
 //O(n^3)
 bool dfs(int k,bool map[M][M]){  
     int t;
     for(int i = 1; i <= m; i++){
         if(map[k][i] && !visit[i]){
             visit[i] = true;
             t = match[i];
             match[i] = k;
             if(t == 0 || dfs(t,map))
                 return true;
             match[i] = t;
         }
     }
     return false;
 }
 int main(){
     int i,sum=0,t,j,u,v;
     cin >> t;
     while(t--){
         sum=0;
         memset(match,0,sizeof(match));
         memset(g,0,sizeof(g));
         scanf("%d%d",&n,&m);
         for(i=1;i<=m;i++){
             scanf("%d%d",&u,&v);
             g[u][v]=true;
         }
         m=n;
         for(i=1;i<=n; i++){
             memset(visit,0,sizeof(visit));
             if(dfs(i,g))  sum++;
         }
         cout << n-sum << endl;
     }
     return 0;
 }
 還有兩個最大匹配模板
 #include <iostream>
 #include <string>
 #include <math.h>
 #include <vector>
 using namespace std;
 #define M 3001
 
 bool g[M][M];
 int mk[M] ,cx[M],pred[M],open[M],cy[M],nx,ny;
 
 
 //邊少適用O(n^3)
 int MaxMatchBFS()
 {
     int i , u , v , t , d , e , cur , tail , res(0) ;
     memset(mk , 0xff , sizeof(mk)) ; 
     memset(cx , 0xff , sizeof(cx)) ;
     memset(cy , 0xff , sizeof(cy)) ;
     for (i = 0 ; i < nx ; i++){
         pred[i] = -1 ;
         for (open[cur = tail = 0] = i ; cur <= tail && cx[i] == -1 ; cur++){
             for (u = open[cur] , v = 0 ; v < ny && cx[i] == -1 ; v ++) if (g[u][v] && mk[v] != i)
             {
                 mk[v] = i ; open[++tail] = cy[v] ; if (open[tail] >= 0) { pred[open[tail]] = u ; continue ; }
                 for (d = u , e = v ; d != -1 ; t = cx[d] , cx[d] = e , cy[e] = d , e = t , d = pred[d]) ;
             }
         }
         if (cx[i] != -1) res++ ;
     }
     return res ;
 }
 
 int path(int u){
     for (int v = 0 ; v < ny ; v++) 
         if (g[u][v] && !mk[v]){
             mk[v] = 1 ; 
             if (cy[v] == -1 || path(cy[v])) {
                 cx[u] = v ; 
                 cy[v] = u ; 
                 return 1 ; 
             }
         } return 0 ;
 }
 //少適用O(n^3)
 int MaxMatchDFS()
 {
     int res(0) ;
     memset(cx , 0xff , sizeof(cx)) ; 
     memset(cy , 0xff , sizeof(cy)) ;
     for (int i = 0 ; i < nx ; i++) 
         if (cx[i] == -1){
             memset(mk , 0 , sizeof(mk)); 
             res += path(i) ;
         }
         return res ;
 }
 最大權匹配,KM算法
 //此KM算法,座標從1開始,記住
 #include <iostream>
 #include <vector>
 #include <math.h>
 using namespace std;
 #define M 110
 
 int n;                // X 的大小
 int lx[M], ly[M];        // 標號
 bool sx[M], sy[M];    // 是否被搜索過
 int match[M];        // Y(i) 與 X(match [i]) 匹配
 
 // 從 X(u) 尋找增廣道路,找到則返回 true
 bool path(int u,int weight[M][M]) {
     sx [u] = true;
     for (int v = 0; v < n; v ++)
         if (!sy [v] && lx[u] + ly [v] == weight [u] [v]) {
             sy [v] = true;
             if (match [v] == -1 || path(match [v],weight)) {
                 match [v] = u;
                 return true;
             }
         }
     return false;
 }
 // 參數 Msum 爲 true ,返回最大權匹配,否則最小權匹配
 int km(bool Msum,int weight[M][M]) {
     int i, j;
     if (!Msum) {
         for (i = 0; i < n; i ++)
             for (j = 0; j < n; j ++)
                 weight [i] [j] = -weight [i] [j];
     }
     // 初始化標號
     for (i = 0; i < n; i ++) {
         lx [i] = -0x1FFFFFFF;
         ly [i] = 0;
         for (j = 0; j < n; j ++)
             if (lx [i] < weight [i] [j])
                 lx [i] = weight [i] [j];
     }  
     memset(match, -1, sizeof (match));
     for (int u = 0; u < n; u ++)
         while (1) {
             memset(sx, 0, sizeof (sx));
             memset(sy, 0, sizeof (sy));
             if (path(u,weight))
                 break;      
             // 修改標號
             int dx = 0x7FFFFFFF;
             for (i = 0; i < n; i ++)
                 if (sx [i])
                     for (j = 0; j < n; j ++)
                         if(!sy [j])
                             dx = min(lx[i] + ly [j] - weight [i] [j], dx);
             for (i = 0; i < n; i ++) {
                 if (sx [i])
                     lx [i] -= dx;
                 if (sy [i])
                     ly [i] += dx;
             }
         }
     
     int sum = 0;
     for (i = 0; i < n; i ++)
         sum += weight [match [i]] [i];
     
     if (!Msum) {
         sum = -sum;
         for (i = 0; i < n; i ++)
             for (j = 0; j < n; j ++)
                 weight [i] [j] = -weight [i] [j];         // 如果需要保持 weight [ ] [ ] 原來的值,這裏需要將其還原
     }
     return sum;
 }
 
 struct Point{
     int r,c;
 };
 int main(){
     int i,j,m;
     freopen("in","r",stdin);
     int w[M][M];
     char c; Point pt;
     while(cin >> n >> m && (n!=0 || m!=0)){
         vector<Point> vh,vm;
         for(i=0;i<n;i++){
             getchar();
             for(j=0;j<m;j++){
                 scanf("%c",&c);
                 if(c=='H'){
                     pt.r=i; pt.c=j;
                     vh.push_back(pt);
                 }
                 if(c=='m'){
                     pt.r=i;pt.c=j;
                     vm.push_back(pt);
                 }
             }
         }
         for(i=0;i<vm.size();i++) for(j=0;j<vh.size();j++) w[i][j]=abs(vm[i].r-vh[j].r)+abs(vm[i].c-vh[j].c);
         n=vm.size();
         cout << km(false,w)<< endl;
     }
 }
 兩種歐拉路
 無向圖:
 #define M 45
 int used[M][M],id[M];
 void dfs(int u,vector<int> g[],vector<int> &vans){  //O(E^2)
     int j,w,v,t;
     for(j=g[u].size()-1;j>=0;j--){
         t=v=g[u][j]; w=u;
         if(v>w) swap(v,w);
         if(used[v][w]!=0){
             used[v][w]--;
             dfs(t,g,vans);
         }
     }
     vans.push_back(u);
 }
 
 有向圖:
 int n,m;
 vector<int> g[M],vans;
 void dfs(int u){   //O(E^2*log(e))
     int j,t;
     Edg et;
     for(j=g[u].size()-1;j>=0;j--){
         et.u=u; et.v=g[u][j];
         if(mp[et]!=0){
             mp[et]--;
             dfs(g[u][j]);
         }
     }
     vans.push_back(u);
 }
 
 【最大流】Edmonds Karp
 //求最小割集合的辦法:
 //設置一個集合A, 最開始A={s},按如下方法不斷擴張A:
 //1 若存在一條邊(u,v), 其流量小於容量,且u屬於A,則v加入A
 //2 若存在(v,u), 其流量大於0,且u屬於A,則v加入A
 
 //A計算完畢,設B=V-A,
 //最大流對應的割集E={(u,v) | u∈A,v∈B}
 //E爲割集,這是一定的
 
 //【最大流】Edmonds Karp算法求最大流,複雜度 O(V E^2)。返回最大流,輸入圖容量
 //矩陣g[M][M],取非零值表示有邊,s爲源點,t爲匯點,f[M][M]返回流量矩陣。
 
 int f[M][M],g[M][M];
 
 int EdmondsKarp(int n,int s,int t){    
     int i,j,k,c,head,tail,flow=0;
     int r[M][M];
     int prev[M],visit[M],q[M];
     for (i=1;i<=n;i++) for (j=1;j<=n;j++) {f[i][j]=0;r[i][j]=g[i][j];} //初始化流量網絡和殘留網絡
     while (1) { //在殘留網絡中找到一條s到t的最短路徑
         head=tail=0;
         memset(visit,0,sizeof(visit));
         q[tail++]=s;
         prev[s]=-1; visit[s]=1;
         while(head!=tail){  //寬度優先搜索從s到t的最短路徑
             k=q[head++];
             for (i=1;i<=n;i++)
                 if (!visit[i] && r[k][i]>0) {
                     visit[i]=1;
                     prev[i]=k;
                     if (i==t) goto next;
                     q[tail++]=i;
                 }
         }
 next:    
         if (!visit[t]) break; //流量已達到最大
         c=99999999;
         j=t;
         while (j!=s) {
             i=prev[j];
             if (c>r[i][j]) c=r[i][j];
             j=i;
         }
         //下面改進流量
         j=t;
         while (j!=s) {
             i=prev[j];
             f[i][j]+=c;
             f[j][i]=-f[i][j];
             r[i][j]=g[i][j]-f[i][j];
             r[j][i]=g[j][i]-f[j][i];
             j=i;
         }
         flow+=c;
         //cout << c << endl;
     }
     return flow;
 }
 dinic
 /* 
 dinic 
 BFS+多路增廣 
 這個模板是OIBH上的Code_Rush的,他寫的Dinic和別人的不太一樣,速度更快 
 O(mn^2) 
 */ 
 
 #include<stdio.h> 
 #include<list> 
 #include<queue> 
 #include<string.h> 
 #include <vector>
 #include <iostream>
 using namespace std; 
 #define M 201
 int pre[M]; 
 int f[M][M],g[M][M]; 
 bool b[M]={0}; 
 
 //g爲輸入的圖容量矩陣,f爲返回流量矩陣
 int dinic(int n,int s,int t) 
 { 
     memset(f,0,sizeof(f));
     int ans=0; 
     while(true) 
     {
         queue<int> q; 
         fill(pre,pre+n+2,-1); 
         fill(b,b+n+2,0); 
         q.push(s);b[s]=1; 
         while(!q.empty()) 
         { 
             int x=q.front();q.pop(); 
             if(x==t)break; 
             for(int i=1;i<=n;i++) 
             {
                 if(!b[i]&&f[x][i]<g[x][i]) 
                 { 
                     pre[i]=x; 
                     b[i]=1; 
                     q.push(i); 
                 } 
             }
         } 
         if(pre[t]==-1)break; 
         for(int i=1;i<=n;i++) 
         {
             if(f[i][t]<g[i][t]&&(i==s||pre[i]!=-1)) 
             { 
                 int v,low=g[i][t]-f[i][t]; 
                 pre[t]=i; 
                 for(v=t;pre[v]!=-1;v=pre[v]) 
                     low=low<g[pre[v]][v]-f[pre[v]][v]?low:g[pre[v]][v]-f[pre[v]][v]; 
                 if(low==0)continue; 
                 for(v=t;pre[v]!=-1;v=pre[v]) 
                 { 
                     f[pre[v]][v]+=low; 
                     f[v][pre[v]]-=low; 
                 } 
                 ans+=low; 
             } 
         }
     } 
     return ans;
 }  
 
 int main(){
     int m,n,i,j,u,v,w;
     while(cin >> m >> n){
         memset(g,0,sizeof(g));
         for(i=0;i<m;i++){
             scanf("%d%d%d",&u,&v,&w);
             g[u][v]+=w;
         }
         cout << dinic(n,1,n) << endl;
     }
 }
 【最小費用最大流】Edmonds Karp對偶算法
 #define M 211
 #define LIM 99999999
 //【最小費用最大流】Edmonds Karp對偶算法,複雜度 O(V^3E^2)。返回最大流,輸入圖
 //容量矩陣g[M][M],費用矩陣w[M][M],取非零值表示有邊,s爲源點,t爲匯點,f[M][M]返
 //迴流量矩陣,minw返回最小費用。
 int g[M][M],w[M][M],minw,f[M][M];
 int DualityEdmondsKarp(int n,int s,int t){    
     int i,j,k,c,quit,flow=0;
     int best[M],prev[M];
     minw=0;
     for (i=1;i<=n;i++) {
         for (j=1;j<=n;j++){
             f[i][j]=0;
             if (g[i][j]) {g[j][i]=0;w[j][i]=-w[i][j];}
         }
     }
     while (1) {
         for (i=1;i<=n;i++) best[i]=LIM;
         best[s]=0;
         do {
             quit=1;
             for (i=1;i<=n;i++){
                 if (best[i]<LIM)
                     for (j=1;j<=n;j++){
                         if (f[i][j]<g[i][j] && best[i]+w[i][j]<best[j]){
                             best[j]=best[i]+w[i][j];
                             prev[j]=i;
                             quit=0;
                         }
                     }
             }
         }while(!quit);
         if (best[t]>=LIM) break;
         c=LIM;
         j=t;
         while (j!=s) {
             i=prev[j];
             if (c>g[i][j]-f[i][j]) c=g[i][j]-f[i][j];
             j=i;
         }
         j=t;
         while (j!=s) {
             i=prev[j];
             f[i][j]+=c;
             f[j][i]=-f[i][j];
             j=i;
         }
         flow+=c; minw+=c*best[t];
     }
     return flow;
 }
 


發佈了25 篇原創文章 · 獲贊 3 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章