Time Limit: 2000MS | Memory Limit: 32768K | |
Total Submissions: 20026 | Accepted: 10539 |
Description
An example is in figure 1. The label x/y of power station u shows that p(u)=x and pmax(u)=y. The label x/y of consumer u shows that c(u)=x and cmax(u)=y. The label x/y of power transport line (u,v) shows that l(u,v)=x and lmax(u,v)=y. The power consumed is Con=6. Notice that there are other possible states of the network but the value of Con cannot exceed 6.
Input
Output
Sample Input
2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20 7 2 3 13 (0,0)1 (0,1)2 (0,2)5 (1,0)1 (1,2)8 (2,3)1 (2,4)7 (3,5)2 (3,6)5 (4,2)7 (4,3)5 (4,5)1 (6,0)5 (0)5 (1)2 (3)2 (4)1 (5)4
Sample Output
15 6
Hint
//dinic 网络流 增广路法的网络流算法 理解起来比较简单,速度也还不错
// 对于该题 : 建立自行建立 S 和 T s和所有发电站相连 所有用户和t相连 cap分别为 pmax cmax
// 其它边都按题目所给的连
// 唉、该类题目的难点在于问题建模、、表示偶才刚刚开始呀、、
//Re了2次、、是因为虽然说m<=n^2但是自行加了边 所以M最好>=20400 我开始只给了了20010....;
#include <iostream> #include <math.h> #include <vector> #include <queue> #include <stack> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int M=20510; const int N=110; const int INF=1000000000; struct Eg { int to; int cap; int flow; int next; }edge[M]; int nu; int node[N]; int level[N]; void add(int from,int to,int cap) { edge[nu].to=to; edge[nu].cap=cap; edge[nu].flow=0; edge[nu].next=node[from]; node[from]=nu++; edge[nu].to=from; edge[nu].cap=0; edge[nu].flow=0; edge[nu].next=node[to]; node[to]=nu++; } int n,np,nc,m; bool BFS(int s,int t) { int u,v,e; memset(level,0,sizeof(level)); level[s]=1; queue<int> Q; Q.push(s); while(!Q.empty()) { u=Q.front(); if(u==t) return true; Q.pop(); for(e=node[u];e!=-1;e=edge[e].next) { v=edge[e].to; if(!level[v]&&edge[e].cap-edge[e].flow>0) { level[v]=level[u]+1; Q.push(v); } } } return false; } int DFS(int u,int maxf,int t) { if(u==t) return maxf; int ret=0,f; int v,e; for(e=node[u];e!=-1;e=edge[e].next) { v=edge[e].to; if(level[v]==level[u]+1&&(edge[e].cap-edge[e].flow)>0) { f=DFS(v,min(maxf-ret,edge[e].cap-edge[e].flow),t); ret+=f; edge[e].flow+=f; edge[e^1].flow-=f; if(ret==maxf) return ret; } } return ret; } int main() { int i; int u,v,z; while(scanf("%d",&n)!=EOF) { scanf("%d %d %d",&np,&nc,&m); memset(node,-1,sizeof(node)); int s=n,t=n+1; n++; nu=0; for(i=0;i<m;i++) { while(getchar()!='('); scanf("%d,%d)%d",&u,&v,&z); add(u,v,z); } for(i=0;i<np;i++) { while(getchar()!='('); scanf("%d)%d",&u,&z); add(s,u,z); } for(i=0;i<nc;i++) { while(getchar()!='('); scanf("%d)%d",&u,&z); add(u,t,z); } int ans=0; while(BFS(s,t)) ans+=DFS(s,INF,t); printf("%d\n",ans); } return 0; }
//由于上面的dinic算法太慢、、我就决定写下 ISAP 。。。好吧、、真的快了好多
#include <iostream>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int M=20510;
const int N=110;
const int INF=1000000000;
struct Eg
{
int to;
int cap;
int next;
}edge[M];
int nu;
int node[N];
void add(int from,int to,int cap)
{
edge[nu].to=to;
edge[nu].cap=cap;
edge[nu].next=node[from];
node[from]=nu++;
edge[nu].to=from;
edge[nu].cap=0;
edge[nu].next=node[to];
node[to]=nu++;
}
int n,np,nc,m;
int h[N],num[N],cur[N],pre[N];
void rev_bfs(int s,int t) //开始没写这个的、、直接照着书上的写,就是让num[0]=N 、、坑爹的就是一直错、、不知道为什么
{
memset(h,0,sizeof(h));
memset(num,0,sizeof(num));
queue<int> Q;
Q.push(t);
int i,e,u,v;
while(!Q.empty())
{
u=Q.front();
Q.pop();
for(e=node[u];e!=-1;e=edge[e].next)
{
v=edge[e].to;
if(!edge[e].cap&&!h[v])
{
h[v]=h[u]+1;
Q.push(v);
}
}
}
for(i=0;i<=t;i++)
num[h[i]]++;
}
int sap(int s,int t)
{
int cur_flow,cur_ans=0;
int i,u,neck,e;
rev_bfs(s,t);
memset(pre,-1,sizeof(pre));
for(i=0;i<=t;i++)
cur[i]=node[i];
u=s;
while(h[s]<=t)
{
if(u==t)
{
cur_flow=INF;
for(i=s;i!=t;i=edge[cur[i]].to)
{
e=cur[i];
if(cur_flow>edge[e].cap)
{
cur_flow=edge[e].cap;
neck=i;
}
}
for(i=s;i!=t;i=edge[cur[i]].to)
{
e=cur[i];
edge[e].cap-=cur_flow;
edge[e^1].cap+=cur_flow;
}
cur_ans+=cur_flow;
u=neck;
}
for(e=cur[u];e!=-1;e=edge[e].next)
if(edge[e].cap&&h[u]==h[edge[e].to]+1)
break;
if(e!=-1)
{
cur[u]=e;
pre[edge[e].to]=u;
u=edge[e].to;
}
else
{
if(--num[h[u]]==0) break;
cur[u]=node[u];
/* int temp=INF; //这段代码应该换成下面的一段代码,原因是在找到路径时找不下去时
for(e=node[u];e!=-1;e=edge[e].next) //这段代码会在那个点停住、、然后、、就等着Over
if(edge[e].cap) //就是因为这个 temp=INF出了问题
temp=min(temp,h[edge[e].to]); //真是教训深刻、、、、
if(temp!=INF)
{
h[u]=temp+1;
++num[h[u]];
if(u!=s) u=pre[u];
}
*/
//错啦 错啦、、、终于找到哪错了、、
int temp=t+1;
for(e=node[u];e!=-1;e=edge[e].next)
if(edge[e].cap)
temp=min(temp,h[edge[e].to]);
h[u]=temp+1;
++num[h[u]];
if(u!=s) u=pre[u];
}
}
return cur_ans;
}
int main()
{
int i;
int u,v,z;
while(scanf("%d",&n)!=EOF)
{
scanf("%d %d %d",&np,&nc,&m);
memset(node,-1,sizeof(node));
int s=n,t=n+1;
// n++;
nu=0;
for(i=0;i<m;i++)
{
while(getchar()!='(');
scanf("%d,%d)%d",&u,&v,&z);
add(u,v,z);
}
for(i=0;i<np;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&z);
add(s,u,z);
}
for(i=0;i<nc;i++)
{
while(getchar()!='(');
scanf("%d)%d",&u,&z);
add(u,t,z);
}
printf("%d\n",sap(s,t));
}
return 0;
}