大致题意:
给出一个由n个点,m条边组成的有向图,给出切掉每条边的花费。给出f个点和得到这个点的收益值。现在要割掉一些边是的1点和某些城市分开,同时你会得到相应的收益值。求总收益的最大值。
大致思路:
网络流经典构图……
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int nMax=2000;
const int mMax=300000;
const int inf=1<<30;
class node{
public:
int u,v,next;
int c;
int cnm,id;
};node edge[mMax];
int ne, head[nMax];
int cur[nMax], ps[nMax], dep[nMax],n,m,ans,cnts,cntt;
bool f[nMax],ff[nMax];
void addedge(int u, int v,int c,int id){ // dinic的加边,还是有点不同的。
edge[ne].u = u;
edge[ne].v = v;
edge[ne].c = c;
edge[ne].next = head[u];
edge[ne].cnm=ne+1;
edge[ne].id=id;
head[u] = ne ++;
edge[ne].u = v;
edge[ne].v = u;
edge[ne].c =0;
edge[ne].next = head[v];
edge[ne].cnm=ne-1;
edge[ne].id=id;
head[v] = ne ++;
}
int dinic(int s, int t){ // dinic模板:源点为s,汇点为t
int tr, res = 0;
int i, j, k, f, r, top;
while(1){
memset(dep, -1, sizeof(dep));
for(f = dep[ps[0]=s] = 0, r = 1; f != r;)
for(i = ps[f ++], j = head[i]; j; j = edge[j].next)
if(edge[j].c && dep[k=edge[j].v] == -1){
dep[k] = dep[i] + 1;
ps[r ++] = k;
if(k == t){
f = r; break;
}
}
if(dep[t] == -1) break;
memcpy(cur, head, sizeof(cur));
i = s, top = 0;
while(1){
if(i == t){
for(tr = inf, k = 0; k < top; k ++)
if(edge[ps[k]].c < tr)
tr = edge[ps[f=k]].c;
for(k = 0; k < top; k ++){
edge[ps[k]].c -= tr;
edge[ps[k]^1].c += tr;
}
i = edge[ps[top=f]].u;
res += tr; //
}
for(j = cur[i]; cur[i]; j = cur[i] = edge[cur[i]].next)
if(edge[j].c && dep[i]+1 == dep[edge[j].v]) break;
if(cur[i]){
ps[top ++] = cur[i];
i = edge[cur[i]].v; //
}else{
if(top == 0) break;
dep[i] = -1;
i = edge[ps[-- top]].u;
}
}
}
return res;
}
void dfs1(int v){
// cout<<"v1 "<<v<<endl;
f[v] = 1;
// cnts++;
for(int i = head[v]; i != 0; i = edge[i].next){
int vs=edge[i].v;
if(f[vs]==0&&edge[i].c)
dfs1(vs);
}
}
void dfs2(int v){
// cout<<"v2 "<<v<<endl;
ff[v] = 1;
// cntt++;
for(int i = head[v]; i != 0; i =edge[i].next){
int vs=edge[i].v;
if(ff[vs]==0&&edge[edge[i].cnm].c)
dfs2(vs);
}
}
int aaa[mMax];
int main(){
int i,cas,a,b,c,maxflow,fuck,s,t,ans,tim=0;
scanf("%d",&cas);
while(cas--){
scanf("%d%d%d",&n,&m,&fuck);
s=1,t=n+1;
ne=2;
memset(head,0,sizeof(head));
for(i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c,i);
}
ans=0;
for(i=1;i<=fuck;i++){
scanf("%d%d",&a,&b);
addedge(a,t,b,inf);
ans+=b;
}
maxflow=dinic(s,t);
ans-=maxflow;
printf("Case %d: %d\n",++tim,ans);
memset(f,0,sizeof(f));
memset(ff,0,sizeof(ff));
dfs1(s);
dfs2(t);
int cnt=0;
for(i=2;i<ne;i+=2){
if(f[edge[i].u]&&ff[edge[i].v]&&!edge[i].c){
if(edge[i].id==inf)continue;
aaa[cnt]=edge[i].id;
// cout<<edge[i].id<<"dwadaw"<<endl;
cnt++;
}
}
cout<<cnt;
for(i=0;i<cnt;i++){
cout<<" "<<aaa[i];
}cout<<endl;
}
return 0;
}