码迷,mamicode.com
首页 > 其他好文 > 详细

网络流n题

时间:2018-12-28 00:09:02      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:sign   记录   ems   net   cto   syn   题目   通过   收录   

近日好不容易在自救之路写完暑训遗留下来的网络流8题,在此回顾一下。

Going Home POJ - 2195 

题意:m要去H,一个H只能容纳一个m,一步一块钱,问最小花费。

思路:最小费用最大流的板子题。有博客用了Dijkstra,不过在我看来,存在负权边的图是不能使用Dijkstra的,所以虽然我曾立誓再也不写SPFA,现在也不得不屈服了。

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 1024;
 19 const int inf = 2.1e9;
 20 const ll Inf = 999999999999999999;
 21 const int mod = 1000000007;
 22 const double eps = 1e-6;
 23 const double pi = acos(-1);
 24 int n,m;
 25 char mp[108][108];
 26 struct node
 27 {
 28     int x,y;
 29 }p1[maxn],p2[maxn];
 30 int Head[maxn],Next[maxn*maxn],v[maxn*maxn],w[maxn*maxn],cap[maxn*maxn],cnt;
 31 int t1,t2;int ans;
 32 void init()
 33 {
 34     t1=1;cnt=t2=ans=0;
 35     memset(Head,-1,sizeof(Head));
 36 }
 37 
 38 void add(int x,int y,int z,int f){
 39 //    cout<<x<<" "<<y<<" "<<z<<endl;
 40     v[cnt]=y;
 41     w[cnt]=z;
 42     cap[cnt]=f;
 43     Next[cnt]=Head[x];
 44     Head[x]=cnt++;
 45 
 46     v[cnt]=x;
 47     w[cnt]=-z;
 48     cap[cnt]=0;
 49     Next[cnt]=Head[y];
 50     Head[y]=cnt++;
 51 }
 52 bool vis[maxn];
 53 int dis[maxn];
 54 int prevv[maxn],preve[maxn];
 55 int s,t;
 56 bool spfa()
 57 {
 58     queue<int>q;
 59     memset(vis,0,sizeof(vis));
 60     for(int i=1;i<=t;i++){
 61         dis[i]=inf;
 62     }
 63 
 64     dis[s]=0;
 65     q.push(s);
 66     while(!q.empty()){
 67         int u=q.front();
 68         q.pop();
 69         vis[u]=false;
 70         for(int k=Head[u];k!=-1;k=Next[k]){
 71             if(cap[k]&&dis[v[k]]>dis[u]+w[k]){
 72                 dis[v[k]]=dis[u]+w[k];
 73                 prevv[v[k]]=u;
 74                 preve[v[k]]=k;
 75 
 76                 if(!vis[v[k]]){
 77                     vis[v[k]]=true;
 78                     q.push(v[k]);
 79                 }
 80             }
 81         }
 82     }
 83     if(dis[t]==inf){return false;}
 84     else return true;
 85 }
 86 int min_cost_flow()
 87 {
 88     while(spfa()){
 89         for(int i=t;i!=s;i=prevv[i]){
 90             int k=preve[i];
 91             cap[k]-=1;
 92             cap[k^1]+=1;
 93         }
 94         ans+=dis[t];
 95     }
 96 
 97 }
 98 
 99 int main()
100 {
101 //    ios::sync_with_stdio(false);
102 //    freopen("in.txt","r",stdin);
103 
104     while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
105         init();
106         for(int i=1;i<=n;i++){
107             scanf("%s",mp[i]+1);
108             for(int j=1;j<=m;j++){
109                 if(mp[i][j]==m){p1[++t1]=node{i,j};}
110                 else if(mp[i][j]==H){p2[++t2]=node{i,j};}
111             }
112         }
113         s=1;t=t1+t2+1;
114         for(int i=2;i<=t1;i++){
115             add(s,i,0,1);
116             for(int j=1;j<=t2;j++){
117                 add(i,j+t1,abs(p1[i].x-p2[j].x)+abs(p1[i].y-p2[j].y),inf);
118             }
119         }
120         for(int i=1;i<=t2;i++){
121             add(i+t1,t,0,1);
122         }
123 
124         min_cost_flow();
125         printf("%d\n",ans);
126     }
127 
128     return 0;
129 }
View Code

 

Dining  POJ - 3281 

题意:给奶牛做了吃的和喝的,每一头奶牛都只能接受某些吃的和喝的,问最多能满足多少奶牛。

思路:拆点。奶牛只能吃一份也只能和一份,那就把它拆成两点,之间的边容量为一。食物和饮料不用担心,从源点或汇点连边的时候,控制边权为1就可以限制没份食物或饮料只被吃一次了。

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 20086;
 19 const int inf = 2.1e9;
 20 const ll Inf = 999999999999999999;
 21 const int mod = 1000000007;
 22 const double eps = 1e-6;
 23 const double pi = acos(-1);
 24 int n,F,D;
 25 int Head[maxn],Next[maxn],v[maxn],w[maxn],cnt;
 26 int s,t;
 27 void init()
 28 {
 29     cnt=0;
 30     memset(Head,-1,sizeof(Head));
 31 }
 32 
 33 void add(int x,int y)
 34 {
 35 //    cout<<x<<" "<<y<<endl;
 36     v[cnt]=y;
 37     Next[cnt]=Head[x];
 38     w[cnt]=1;
 39     Head[x]=cnt++;
 40 
 41     v[cnt]=x;
 42     Next[cnt]=Head[y];
 43     w[cnt]=0;
 44     Head[y]=cnt++;
 45 }
 46 
 47 int food(int x)
 48 {
 49     return 2*n+1+x;
 50 }
 51 
 52 int drink(int x)
 53 {
 54     return 2*n+1+F+x;
 55 }
 56 
 57 int nu1(int x)
 58 {
 59     return x+1;
 60 }
 61 
 62 int nu2(int x)
 63 {
 64     return x+n+1;
 65 }
 66 
 67 void build()
 68 {
 69     s=1;t=drink(D)+1;
 70     for(int i=1;i<=F;i++){
 71         add(s,food(i));
 72     }
 73     for(int i=1;i<=D;i++){
 74         add(drink(i),t);
 75     }
 76     for(int i=1;i<=n;i++){
 77         add(nu1(i),nu2(i));
 78     }
 79 }
 80 
 81 int vis[maxn],num[maxn];
 82 
 83 
 84 bool bfs()
 85 {
 86     memset(vis,0,sizeof(vis));
 87     for(int i=1;i<=2*n+1+F+D+8;i++){
 88         num[i]=Head[i];
 89     }
 90     vis[s]=1;
 91     queue<int>q;
 92     q.push(s);
 93     int r=0;
 94     while(!q.empty()){
 95         int u=q.front();
 96         q.pop();
 97         int k=Head[u];
 98         while(k!=-1){
 99             if(!vis[v[k]]&&w[k]){
100                 vis[v[k]]=vis[u]+1;
101                 q.push(v[k]);
102             }
103             k=Next[k];
104         }
105     }
106     return vis[t];
107 }
108 
109 int dfs(int u,int f)
110 {
111     if(u==t){return f;}
112     int &k=num[u];
113     int sum=0;
114     while(k!=-1){
115         if(vis[v[k]]==vis[u]+1&&w[k]){
116             int d=dfs(v[k],min(f,w[k]));
117             f-=d;
118             w[k]-=d;
119             w[k^1]+=d;
120             sum+=d;
121         }
122         k=Next[k];
123     }
124     return sum;
125 }
126 
127 int Dinic()
128 {
129     int ans=0;
130     while(bfs()){
131         int f;
132         while((f=dfs(s,inf))>0){
133             ans+=f;
134         }
135     }
136     return ans;
137 }
138 
139 
140 int main()
141 {
142 //    ios::sync_with_stdio(false);
143 //    freopen("in.txt","r",stdin);
144     init();
145     scanf("%d%d%d",&n,&F,&D);
146     for(int i=1;i<=n;i++){
147         int m1,m2;
148         scanf("%d%d",&m1,&m2);
149         int num;
150         for(int j=1;j<=m1;j++){
151             scanf("%d",&num);
152             add(food(num),nu1(i));
153         }
154         for(int j=1;j<=m2;j++){
155             scanf("%d",&num);
156             add(nu2(i),drink(num));
157         }
158     }
159     build();
160     printf("%d\n",Dinic());
161     return 0;
162 }
View Code

 

Power Network POJ - 1459 

题意:有发电厂用来发电,有用户用来用电,用中间商不赚差价,问电力的最大流量。

思路:好像也是一个板子题,就是输入有些许麻烦。

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 30086;
 19 const int inf = 2.1e9;
 20 const ll Inf = 999999999999999999;
 21 const int mod = 1000000007;
 22 const double eps = 1e-6;
 23 const double pi = acos(-1);
 24 
 25 int n,np,nc,m;
 26 int s,t;
 27 int Head[maxn],Next[maxn],v[maxn],w[maxn],cnt;
 28 
 29 void init()
 30 {
 31     s=n;t=n+1;
 32     memset(Head,-1,sizeof(Head));
 33     cnt=0;
 34 }
 35 
 36 void add(int x,int y,int z)
 37 {
 38 //    cout<<x<<" "<<y<<" "<<z<<endl;
 39     if(x==y){return;}
 40     v[cnt]=y;
 41     w[cnt]=z;
 42     Next[cnt]=Head[x];
 43     Head[x]=cnt++;
 44 
 45     v[cnt]=x;
 46     w[cnt]=0;
 47     Next[cnt]=Head[y];
 48     Head[y]=cnt++;
 49 }
 50 
 51 char str[maxn];
 52 int vis[maxn],num[maxn];
 53 
 54 bool bfs()
 55 {
 56     memset(vis,0,sizeof(vis));
 57     for(int i=0;i<=t;i++){
 58         num[i]=Head[i];
 59     }
 60     vis[s]=1;
 61     queue<int>q;
 62     q.push(s);
 63     int r=0;
 64     while(!q.empty()){
 65         int u=q.front();
 66         q.pop();
 67         int k=Head[u];
 68         while(k!=-1){
 69             if(!vis[v[k]]&&w[k]){
 70                 vis[v[k]]=vis[u]+1;
 71                 q.push(v[k]);
 72             }
 73             k=Next[k];
 74         }
 75     }
 76     return vis[t];
 77 }
 78 
 79 int dfs(int u,int f)
 80 {
 81     if(u==t){return f;}
 82     int &k=num[u];
 83     int sum=0;
 84     while(k!=-1){
 85         if(vis[v[k]]==vis[u]+1&&w[k]){
 86             int d=dfs(v[k],min(f,w[k]));
 87             f-=d;
 88             w[k]-=d;
 89             w[k^1]+=d;
 90             sum+=d;
 91         }
 92         k=Next[k];
 93     }
 94     return sum;
 95 }
 96 
 97 int Dinic()
 98 {
 99     int ans=0;
100     while(bfs()){
101         int f;
102         while((f=dfs(s,inf))>0){
103             ans+=f;
104         }
105     }
106     return ans;
107 }
108 
109 
110 
111 int main()
112 {
113 //    ios::sync_with_stdio(false);
114 //    freopen("in.txt","r",stdin);
115 
116     while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF){
117         init();
118         for(int i=1;i<=m;i++){
119             scanf("%s",str);
120             int len =strlen(str);
121             int j,num = 0;
122             int x,y,z;
123             for(j=1;j<len;j++){
124                 if(str[j]>=0&&str[j]<=9){num=num*10+str[j]-0;}
125                 else break;
126             }
127             x=num;num=0;
128             for(j++;j<len;j++){
129                 if(str[j]>=0&&str[j]<=9){num=num*10+str[j]-0;}
130                 else break;
131             }
132             y=num;num=0;
133             for(j++;j<len;j++){
134                 if(str[j]>=0&&str[j]<=9){num=num*10+str[j]-0;}
135                 else break;
136             }
137             z=num;
138             add(x,y,z);
139         }
140 
141 
142         for(int i=1;i<=np;i++){
143             scanf("%s",str);
144             int len = strlen(str);
145             int j=0,x,y,num=0;
146             for(j++;j<len;j++){
147                 if(str[j]>=0&&str[j]<=9){num=num*10+str[j]-0;}
148                 else break;
149             }
150             x=num;num=0;
151             for(j++;j<len;j++){
152                 if(str[j]>=0&&str[j]<=9){num=num*10+str[j]-0;}
153                 else break;
154             }
155             y=num;num=0;
156             add(s,x,y);
157         }
158         for(int i=1;i<=nc;i++){
159             scanf("%s",str);
160             int len = strlen(str);
161             int j=0,x,y,num=0;
162             for(j++;j<len;j++){
163                 if(str[j]>=0&&str[j]<=9){num=num*10+str[j]-0;}
164                 else break;
165             }
166             x=num;num=0;
167             for(j++;j<len;j++){
168                 if(str[j]>=0&&str[j]<=9){num=num*10+str[j]-0;}
169                 else break;
170             }
171             y=num;num=0;
172             add(x,t,y);
173         }
174         printf("%d\n",Dinic());
175     }
176 
177     return 0;
178 }
View Code

 

Escape  HDU - 3605

题意:有很多人想跑路了,可是他们都有自己想去的星球,每个星球也有自己的容量,问所有人是否都可以去到自己的想去的星球上。

思路:这个人很多,把相同目的地的人合在一起才行。

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 500086;
 19 const int inf = 2.1e9;
 20 const ll Inf = 999999999999999999;
 21 const int mod = 1000000007;
 22 const double eps = 1e-6;
 23 const double pi = acos(-1);
 24 
 25 int Head[2000],Next[maxn],v[maxn],w[maxn],cnt;
 26 int n,m,s,t;
 27 int vis[2000],num[2000];
 28 int sum[1228];
 29 void init()
 30 {
 31     s=1050+m+1;t=s+1;
 32     memset(sum,0,sizeof(sum));
 33     for(int i=0;i<=t;i++){
 34         Head[i]=-1;
 35     }
 36     cnt=0;
 37 }
 38 void add(int x,int y,int z)
 39 {
 40 //    cout<<x<<" "<<y<<" "<<z<<endl;
 41     if(x==y){return;}
 42     v[cnt]=y;
 43     w[cnt]=z;
 44     Next[cnt]=Head[x];
 45     Head[x]=cnt++;
 46 
 47     v[cnt]=x;
 48     w[cnt]=0;
 49     Next[cnt]=Head[y];
 50     Head[y]=cnt++;
 51 }
 52 
 53 bool bfs()
 54 {
 55     memset(vis,0,sizeof(vis));
 56     for(int i=0;i<=t;i++){
 57         num[i]=Head[i];
 58     }
 59     vis[s]=1;
 60     queue<int>q;
 61     q.push(s);
 62     int r=0;
 63     while(!q.empty()){
 64         int u=q.front();
 65         q.pop();
 66         int k=Head[u];
 67         while(k!=-1){
 68             if(!vis[v[k]]&&w[k]){
 69                 vis[v[k]]=vis[u]+1;
 70                 q.push(v[k]);
 71             }
 72             k=Next[k];
 73         }
 74     }
 75     return vis[t];
 76 }
 77 
 78 int dfs(int u,int f)
 79 {
 80     if(u==t){return f;}
 81     int &k=num[u];
 82     int sum=0;
 83     while(k!=-1){
 84         if(vis[v[k]]==vis[u]+1&&w[k]){
 85             int d=dfs(v[k],min(f,w[k]));
 86             f-=d;
 87             w[k]-=d;
 88             w[k^1]+=d;
 89             sum+=d;
 90         }
 91         k=Next[k];
 92     }
 93     return sum;
 94 }
 95 
 96 int Dinic()
 97 {
 98     int ans=0;
 99     while(bfs()){
100         int f;
101         while((f=dfs(s,inf))>0){
102             ans+=f;
103         }
104     }
105     return ans;
106 }
107 
108 int plant(int x)
109 {
110     return x+1025;
111 }
112 
113 int main()
114 {
115 //    ios::sync_with_stdio(false);
116 //    freopen("in.txt","r",stdin);
117 
118     while(scanf("%d%d",&n,&m)!=EOF){
119         init();
120         for(int i=0;i<n;i++){
121             int num = 0,x;
122             for(int j=0;j<m;j++){
123                 scanf("%d",&x);
124                 num=num*2+x;
125             }
126             sum[num]++;
127         }
128         for(int i=0;i<1024;i++){
129             add(s,i,sum[i]);
130         }
131         for(int i=0;i<1024;i++){
132             if(sum[i]){
133                 int ss = i;
134                 for(int j=m;j>=1;j--){
135                     if(ss&1){add(i,plant(j),inf);}
136                     ss>>=1;
137                 }
138             }
139         }
140         for(int i=1;i<=m;i++){
141             int num = 0;
142             scanf("%d",&num);
143             add(plant(i),t,num);
144         }
145         if(Dinic()==n){printf("YES\n");}
146         else printf("NO\n");
147     }
148 
149     return 0;
150 }
View Code

 

ACM Computer Factory POJ - 3436 

题意:造电脑了,每一个工厂有若干入状态和一个出状态,问整个系统的最大产量。

思路:枚举,如果有某家工厂的某个入状态和另一家工厂的出厂状态相同,那就连一条边。题目要求输出路径,整个在Dinic的DFS里面加记录一下就行了,这个题是有SPJ的,所以可以写的随心一点

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 100086;
 19 const int inf = 2.1e9;
 20 const ll Inf = 999999999999999999;
 21 const int mod = 1000000007;
 22 const double eps = 1e-6;
 23 const double pi = acos(-1);
 24 int p,n;
 25 int vis[155],num[155];
 26 int Head[155],Next[maxn],v[maxn],w[maxn],cnt;
 27 vector<int>num1[155];
 28 int num2[155];
 29 int s,t,flows;
 30 void init()
 31 {
 32     memset(Head,-1,sizeof(Head));
 33     s=2*n+1;t=s+1;
 34 }
 35 void add(int x,int y,int z)
 36 {
 37 //    cout<<x<<" "<<y<<" "<<z<<endl;
 38     if(x==y){return;}
 39     v[cnt]=y;
 40     w[cnt]=z;
 41     Next[cnt]=Head[x];
 42     Head[x]=cnt++;
 43 
 44     v[cnt]=x;
 45     w[cnt]=0;
 46     Next[cnt]=Head[y];
 47     Head[y]=cnt++;
 48 }
 49 
 50 bool bfs()
 51 {
 52 
 53     memset(vis,0,sizeof(vis));
 54     for(int i=0;i<=t;i++){
 55         num[i]=Head[i];
 56     }
 57     vis[s]=1;
 58     queue<int>q;
 59     q.push(s);
 60     int r=0;
 61     while(!q.empty()){
 62         int u=q.front();
 63         q.pop();
 64         int k=Head[u];
 65         while(k!=-1){
 66             if(!vis[v[k]]&&w[k]){
 67                 vis[v[k]]=vis[u]+1;
 68                 q.push(v[k]);
 69             }
 70             k=Next[k];
 71         }
 72     }
 73     return vis[t];
 74 }
 75 struct node
 76 {
 77     int u,v,w;
 78 };
 79 queue<node>q;
 80 int anss;
 81 int dfs(int u,int f)
 82 {
 83     if(u==t){return f;}
 84     int &k=num[u];
 85     int sum=0;
 86     while(k!=-1){
 87         if(vis[v[k]]==vis[u]+1&&w[k]){
 88             int d=dfs(v[k],min(f,w[k]));
 89             if(d>0){
 90                 if(u!=s&&v[k]!=t&&u>n){
 91                     q.push(node{u-n,v[k],d});
 92                     anss++;
 93                 }
 94                 w[k]-=d;
 95                 w[k^1]+=d;
 96                 return d;
 97             }
 98         }
 99         k=Next[k];
100     }
101     return sum;
102 }
103 int Dinic()
104 {
105     int ans=0;
106     while(bfs()){
107         int f;
108         while((f=dfs(s,inf))>0){
109             ans+=f;
110         }
111     }
112     return ans;
113 }
114 int a[15];
115 int u;
116 void num_dfs(int t,int ans)
117 {
118     if(t==p+1){
119         num1[u].push_back(ans);
120         return;
121     }
122     if(a[t]==0){
123         num_dfs(t+1,ans*2);
124     }
125     else if(a[t]==1){
126         num_dfs(t+1,ans*2+1);
127     }
128     else{
129         num_dfs(t+1,ans*2);
130         num_dfs(t+1,ans*2+1);
131     }
132 }
133 
134 int sta(int x)
135 {
136     return x;
137 }
138 
139 int endd(int x)
140 {
141     return x+n;
142 }
143 
144 int main()
145 {
146 //    ios::sync_with_stdio(false);
147 //    freopen("in.txt","r",stdin);
148 
149     scanf("%d%d",&p,&n);
150     init();
151     for(int i=1;i<=n;i++){
152         num1[i].clear();num2[i]=0;
153     }
154     for(int i=1;i<=n;i++){
155         scanf("%d",&flows);
156         add(sta(i),endd(i),flows);
157         u=i;
158         for(int j=1;j<=p;j++){
159             scanf("%d",&a[j]);
160         }
161         num_dfs(1,0);
162         for(int j=1;j<=p;j++){
163             int h;
164             scanf("%d",&h);
165             num2[i]=num2[i]*2+h;
166         }
167     }
168     for(int i=1;i<=n;i++){
169         int siz = num1[i].size();
170         if(num2[i]==(1<<p)-1){
171             add(endd(i),t,inf);
172         }
173         for(int j=0;j<siz;j++){
174             if(num1[i][j]==0){add(s,sta(i),inf);}
175             for(int k=1;k<=n;k++){
176                 if(num1[i][j]==num2[k]){
177                     add(endd(k),sta(i),inf);
178                 }
179             }
180         }
181     }
182     printf("%d ",Dinic());
183     printf("%d\n",anss);
184     while(!q.empty()){
185         printf("%d %d %d\n",q.front().u,q.front().v,q.front().w);
186         q.pop();
187     }
188     return 0;
189 }
View Code

 

Minimum Cost POJ - 2516

题意:有供货源给商店老板供货,每一种商品都有各自的对于每一个供应商都有其存储量,对于每一个商店都有其需求量,对于每一对商店和供应商的组合,运输都有其花费,求最大流量时的最大花费。

思路:每一种商品分别建图,不然会TLE,因为边太多了。

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 400086;
 19 const int inf = 2.1e9;
 20 //const ll Inf = 999999999999999999;
 21 //const int mod = 1000000007;
 22 //const double eps = 1e-6;
 23 //const double pi = acos(-1);
 24 
 25 int n,m,k,ans;
 26 int Head[5050*2],Next[maxn],v[maxn],cap[maxn],w[maxn],cnt;
 27 bool vis[5050*2];
 28 int dis[5050*2];
 29 int prevv[5050*2];
 30 int preve[5050*2];
 31 int s,t,all;
 32 void init()
 33 {
 34     s=0;t=2*k*(n+m)+1;
 35     memset(Head,-1,sizeof(Head));
 36     ans=cnt=0;
 37 }
 38 
 39 int sshop(int x,int s)
 40 {
 41     return 2*k*(x-1)+s;
 42 }
 43 
 44 int eshop(int x,int y)
 45 {
 46     return sshop(x,y)+k;
 47 }
 48 
 49 int ssup(int x,int y)
 50 {
 51     return n*k*2+y+(x-1)*k*2;
 52 }
 53 
 54 int esup(int x,int y)
 55 {
 56     return ssup(x,y)+k;
 57 }
 58 
 59 void add(int x,int y,int z,int f){
 60 //    cout<<x<<" "<<y<<" "<<z<<" "<<f<<endl;
 61     v[cnt]=y;
 62     w[cnt]=z;
 63     cap[cnt]=f;
 64     Next[cnt]=Head[x];
 65     Head[x]=cnt++;
 66 
 67     v[cnt]=x;
 68     w[cnt]=-z;
 69     cap[cnt]=0;
 70     Next[cnt]=Head[y];
 71     Head[y]=cnt++;
 72 }
 73 
 74 bool spfa(){
 75     queue<int>q;
 76     memset(vis,0,sizeof(vis));
 77     for(int i=0;i<=t;i++){
 78         dis[i]=inf;
 79     }
 80 
 81     dis[s]=0;
 82     q.push(s);
 83     while(!q.empty()){
 84         int u=q.front();
 85         q.pop();
 86         vis[u]=false;
 87         for(int k=Head[u];k!=-1;k=Next[k]){
 88             if(cap[k]&&dis[v[k]]>dis[u]+w[k]){
 89                 dis[v[k]]=dis[u]+w[k];
 90                 prevv[v[k]]=u;
 91                 preve[v[k]]=k;
 92 
 93                 if(!vis[v[k]]){
 94                     vis[v[k]]=true;
 95                     q.push(v[k]);
 96                 }
 97             }
 98         }
 99     }
100     if(dis[t]==inf){return false;}
101     else return true;
102 }int anss=0;
103 int min_cost_flow(){
104     while(spfa()){
105         anss++;
106         for(int i=t;i!=s;i=prevv[i]){
107             int k=preve[i];
108             cap[k]-=1;
109             cap[k^1]+=1;
110         }
111         ans+=dis[t];
112     }
113     return ans;
114 }
115 
116 int input1[105][105];
117 int input2[105][105];
118 
119 
120 
121 void build(int kk)
122 {
123     init();
124     for(int i=1;i<=n;i++){
125         add(sshop(i,kk),eshop(i,kk),0,input1[i][kk]);
126     }
127     for(int i=1;i<=m;i++){
128         add(ssup(i,kk),esup(i,kk),0,input2[i][kk]);
129     }
130     for(int i=1;i<=n;i++){
131         add(s,sshop(i,kk),0,inf);
132     }
133     for(int i=1;i<=m;i++){
134         add(esup(i,kk),t,0,inf);
135     }
136 }
137 
138 int main()
139 {
140 //    ios::sync_with_stdio(false);
141 //    freopen("in.txt","r",stdin);
142     while(scanf("%d%d%d",&n,&m,&k)!=EOF&&(n||m||k)){
143         init();all=0;anss=0;
144         for(int i=1;i<=n;i++){
145             for(int j=1;j<=k;j++){
146                 int input;
147                 scanf("%d",&input);
148                 all+=input;
149                 input1[i][j]=input;
150             }
151         }
152 
153         for(int i=1;i<=m;i++){
154             for(int j=1;j<=k;j++){
155                 int input;
156                 scanf("%d",&input);
157                 input2[i][j]=input;
158             }
159         }
160         int ans=0;
161         for(int i=1;i<=k;i++){
162             build(i);
163             for(int j=1;j<=n;j++){
164                 for(int s=1;s<=m;s++){
165                     int input;
166                     scanf("%d",&input);
167                     add(eshop(j,i),ssup(s,i),input,inf);
168                 }
169             }
170             ans+=min_cost_flow();
171         }
172         if(anss!=all)ans=-1;
173             printf("%d\n",ans);
174     }
175 
176     return 0;
177 }
View Code

 

Cyclic Tour  HDU - 1853 

题意:某个人要转圈圈,每个点之走一次,问最小花费。

思路:把每个点拆开(pi1和pi2),有边的话就建一条pi2到pj1的边,源点到每个p1建边容量为一,花费为0,汇点同理,然后网络流即可。建图虽然没有体现环,但是如果网络流跑满了,就说明每个点都在环内了(每个点的出度和入度都是1)

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 100086;
 19 const int inf = 2.1e9;
 20 const ll Inf = 999999999999999999;
 21 const int mod = 1000000007;
 22 const double eps = 1e-6;
 23 const double pi = acos(-1);
 24 int m,n,s,t,ans,anss;
 25 int Head[308],Next[maxn],v[maxn],w[maxn],cap[maxn],cnt;
 26 bool vis[308];
 27 int dis[308],prevv[308],preve[308];
 28 void init()
 29 {
 30     anss=0;
 31     memset(Head,-1,sizeof(Head));
 32     s=0,t=2*n+1;ans=cnt=0;
 33 }
 34 void add(int x,int y,int z,int f){
 35 //    cout<<x<<C" "<<y<<" "<<z<<" "<<f<<endl;
 36     v[cnt]=y;
 37     w[cnt]=z;
 38     cap[cnt]=f;
 39     Next[cnt]=Head[x];
 40     Head[x]=cnt++;
 41 
 42     v[cnt]=x;
 43     w[cnt]=-z;
 44     cap[cnt]=0;
 45     Next[cnt]=Head[y];
 46     Head[y]=cnt++;
 47 }
 48 
 49 bool spfa(){
 50     queue<int>q;
 51     memset(vis,0,sizeof(vis));
 52     for(int i=0;i<=t;i++){
 53         dis[i]=inf;
 54     }
 55 
 56     dis[s]=0;
 57     q.push(s);
 58     while(!q.empty()){
 59         int u=q.front();
 60         q.pop();
 61         vis[u]=false;
 62         for(int k=Head[u];k!=-1;k=Next[k]){
 63             if(cap[k]&&dis[v[k]]>dis[u]+w[k]){
 64                 dis[v[k]]=dis[u]+w[k];
 65                 prevv[v[k]]=u;
 66                 preve[v[k]]=k;
 67 
 68                 if(!vis[v[k]]){
 69                     vis[v[k]]=true;
 70                     q.push(v[k]);
 71                 }
 72             }
 73         }
 74     }
 75 //    fuck(dis[t])
 76     if(dis[t]==inf){return false;}
 77     else return true;
 78 }
 79 int min_cost_flow(){
 80     while(spfa()){
 81         anss++;
 82         for(int i=t;i!=s;i=prevv[i]){
 83             int k=preve[i];
 84             cap[k]-=1;
 85             cap[k^1]+=1;
 86         }
 87         ans+=dis[t];
 88     }
 89 //    fuck(ans)
 90     return ans;
 91 }
 92 
 93 int main()
 94 {
 95 //    ios::sync_with_stdio(false);
 96 //    freopen("in.txt","r",stdin);
 97 
 98     while(scanf("%d%d",&n,&m)!=EOF){
 99         init();
100         for(int i=1;i<=m;i++){
101             int x,y,z;
102             scanf("%d%d%d",&x,&y,&z);
103             add(x,y+n,z,1);
104         }
105 
106         for(int i=1;i<=n;i++){
107             add(i+n,t,0,1);
108             add(s,i,0,1);
109         }
110         int ans = min_cost_flow();
111         if(anss!=n){ans=-1;}
112         printf("%d\n",ans);
113     }
114 
115 
116 
117     return 0;
118 }
View Code

 

Fox And Dinner CodeForces - 510E 

题意:n个数字,组成若干个环,相邻的两个数相加必须是质数,输出组合方式。

思路:和上一题相同,就是跑满之后才能看出来满足题意。具体方法是,分为奇数和偶数,源点到奇数的权值为2,偶数到汇点的权值是2,如果相加为质数,奇数到偶数权值为1.跑满的话,说明每个数旁边都有两个数,满足题意。然后通过深搜找出途中的环。因为满足题意,每个点只有两个相邻的点,所以可以无脑向下搜。注意网络流途中的边权变化,导致技术和偶数的有效边权值是不一样的。

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 100086;
 19 const int inf = 2.1e9;
 20 const ll Inf = 999999999999999999;
 21 const int mod = 1000000007;
 22 const double eps = 1e-6;
 23 const double pi = acos(-1);
 24 int n,s,t;
 25 int nums[206];
 26 int vis[maxn],num[maxn];
 27 int prime[maxn],cur;
 28 bool check[maxn];
 29 int Head[208],Next[maxn],v[maxn],w[maxn],cnt;
 30 
 31 void init()
 32 {
 33     memset(Head,-1,sizeof(Head));
 34     cnt=0;
 35     s=0,t=n+1;
 36 }
 37 
 38 void primes()
 39 {
 40     for(int i=2;i<20086;i++){
 41         if(!check[i]){
 42             prime[cur++]=i;
 43         }
 44         for(int j=0;j<cur;j++){
 45             if(i*prime[j]>20086){
 46                 break;
 47             }
 48             check[i*prime[j]]=i;
 49             if(i%prime[j]==0){
 50                 break;
 51             }
 52         }
 53     }
 54 }
 55 
 56 
 57 
 58 void add(int x,int y,int z)
 59 {
 60 //    if(x!=s&&y!=t)cout<<x<<" "<<y<<" "<<z<<endl;
 61     if(x==y){return;}
 62     v[cnt]=y;
 63     w[cnt]=z;
 64     Next[cnt]=Head[x];
 65     Head[x]=cnt++;
 66 
 67     v[cnt]=x;
 68     w[cnt]=0;
 69     Next[cnt]=Head[y];
 70     Head[y]=cnt++;
 71 }
 72 
 73 bool bfs()
 74 {
 75     memset(vis,0,sizeof(vis));
 76     for(int i=0;i<=t;i++){
 77         num[i]=Head[i];
 78     }
 79     vis[s]=1;
 80     queue<int>q;
 81     q.push(s);
 82     int r=0;
 83     while(!q.empty()){
 84         int u=q.front();
 85         q.pop();
 86         int k=Head[u];
 87         while(k!=-1){
 88             if(!vis[v[k]]&&w[k]){
 89                 vis[v[k]]=vis[u]+1;
 90                 q.push(v[k]);
 91             }
 92             k=Next[k];
 93         }
 94     }
 95     return vis[t];
 96 }
 97 
 98 int dfs(int u,int f)
 99 {
100     if(u==t){return f;}
101     int &k=num[u];
102     int sum=0;
103     while(k!=-1){
104         if(vis[v[k]]==vis[u]+1&&w[k]){
105             int d=dfs(v[k],min(f,w[k]));
106             if(d>0){
107                 w[k]-=d;
108                 w[k^1]+=d;
109                 return d;
110             }
111         }
112         k=Next[k];
113     }
114     return sum;
115 }
116 int Dinic()
117 {
118     int ans=0;
119     while(bfs()){
120         int f;
121         while((f=dfs(s,inf))>0){
122             ans+=f;
123         }
124     }
125     return ans;
126 }
127 stack<int>st;
128 void dfs(int t)
129 {
130     vis[t]=1;
131     st.push(t);
132     for(int k=Head[t];k!=-1;k=Next[k]){
133         if(v[k]==0||v[k]==n+1){continue;}
134         if(vis[v[k]]){continue;}
135         if(nums[t]%2==0&&w[k]){dfs(v[k]);}
136         if(nums[t]%2==1&&!w[k]){dfs(v[k]);}
137     }
138     vis[t]=-1;
139 }
140 
141 
142 queue<int>q[208];
143 int main()
144 {
145 //    ios::sync_with_stdio(false);
146 //    freopen("in.txt","r",stdin);
147 
148     primes();
149     scanf("%d",&n);
150     for(int i=1;i<=n;i++){
151         scanf("%d",&nums[i]);
152     }init();
153     for(int i=1;i<=n;i++){
154         if(nums[i]&1){add(s,i,2);}
155         else{add(i,t,2);}
156         for(int j=i+1;j<=n;j++){
157             if(!check[nums[i]+nums[j]]){
158                 if(nums[i]&1){add(i,j,1);}
159                 else{add(j,i,1);}
160             }
161         }
162     }
163     if(Dinic()!=n){printf("Impossible\n");return 0;}
164 
165     int numi = 0;
166     memset(vis,0,sizeof(vis));
167     for(int i=1;i<=n;i++){
168         if(!vis[i]){
169             dfs(i);numi++;
170             while(!st.empty()){
171                 q[i].push(st.top());
172                 st.pop();
173             }
174         }
175     }
176     printf("%d\n",numi);
177     for(int i=1;i<=n;i++){
178         if(!q[i].empty()){
179             printf("%d",q[i].size());
180             while(!q[i].empty()){
181                 printf(" %d",q[i].front());
182                 q[i].pop();
183             }
184             printf("\n");
185         }
186 
187     }
188     return 0;
189 }
View Code

 

以上8题全靠建图+贴板子,建好了图就完成了90%。

这就是暑训的8题了。接下来还是暑训网络流的题,不过被收录到图论专题中,被学长标了较难,所以本菜鸡现在比较慌。

 

网络流n题

标签:sign   记录   ems   net   cto   syn   题目   通过   收录   

原文地址:https://www.cnblogs.com/ZGQblogs/p/10188207.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!