You are the hero who saved your country. As promised, the king will give you some cities of the country, and you can choose which ones to own!
But don’t get too excited. The cities you take should NOT be reachable from the capital – the king does not want to accidentally enter your area. In order to satisfy this condition, you have to destroy some roads. What’s worse, you have to pay for that – each road is associated with some positive cost. That is, your final income is the total value of the cities you take, minus the total cost of destroyed roads.
Note that each road is a unidirectional, i.e only one direction is available. Some cities are reserved for the king, so you cannot take any of them even if they’re unreachable from the capital. The capital city is always the city number 1.
Input
The first line contains a single integer T (T <= 20), the number of test cases. Each case begins with three integers n, m, f (1 <= f < n <= 1000, 1 <= m < 100000), the number of cities, number of roads, and number of cities that you can take. Cities are numbered 1 to n. Each of the following m lines contains three integers u, v, w, denoting a road from city u to city v, with cost w. Each of the following f lines contains two integers u and w, denoting an available city u, with value w.
Output
For each test case, print the case number and the best final income in the first line. In the second line, print e, the number of roads you should destroy, followed by e integers, the IDs of the destroyed roads. Roads are numbered 1 to m in the same order they appear in the input. If there are more than one solution, any one will do.
Sample Input
2
4 4 2
1 2 2
1 3 3
3 2 4
2 4 1
2 3
4 4
4 4 2
1 2 2
1 3 3
3 2 1
2 4 1
2 3
4 4
Sample Output
Case 1: 3
1 4
Case 2: 4
2 1 3
分析: 建图: 先按照题中给的边建好之后,然后再将所有可以选择的点,以边权为得到的费用和汇点相连接。
为什么这样就可以满足题意呢? 如果要是割与汇点相连接的边,那么就说明 这条边所代表的城市 不能够选择,因为不能够通过其余的边来阻断,说明用其余的边来阻断没有截断 这个城市省钱,这就说明 通过割段别的边来阻断的花费 要超过得到的钱。
求最小割:S-T
然后 从S跑一遍,遍历得到所有 S集合的点,然后枚举所有S集合的点,如果有指向T集合的点的边,那么这条边一定为割边。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
const int N = 1000*2+11;
const int M = 1e6+11;
const int inf = 0x3f3f3f3f;
struct Edge {
int form,to,cap,flow,nexts,id;
}edge[M];
int head[N],top;
void init(){
memset(head,-1,sizeof(head));
top=0;
}
void addedge(int a,int b,int c,int id){
Edge e={a,b,c,0,head[a],id};
edge[top]=e;head[a]=top++;
Edge ee={b,a,0,0,head[b],id};
edge[top]=ee;head[b]=top++;
}
int vis[N],dis[N];
int cur[N];
bool bfs(int st,int ed){
queue<int>Q;
memset(vis,0,sizeof(vis));
memset(dis,-1,sizeof(dis));
Q.push(st);vis[st]=1;dis[st]=1;
while(!Q.empty()){
int now=Q.front();Q.pop();
for(int i=head[now];i!=-1;i=edge[i].nexts){
Edge e=edge[i];
if(!vis[e.to]&&e.cap-e.flow>0){
vis[e.to]=1;
dis[e.to]=dis[now]+1;
if(e.to==ed) return 1;
Q.push(e.to);
}
}
}
return 0;
}
int dfs(int now,int a,int ed){
if(a==0||now==ed) return a;
int flow=0,f;
for(int &i=cur[now];i!=-1;i=edge[i].nexts){
Edge &e=edge[i];
if(dis[e.to]==dis[now]+1&&(f=dfs(e.to,min(e.cap-e.flow,a),ed))>0){
e.flow+=f;
flow+=f;
edge[i^1].flow-=f;
a-=f;
if(a==0) break;
}
}
return flow;
}
int max_flow(int st ,int ed){
int flow=0;
while(bfs(st,ed)){
memcpy(cur,head,sizeof(head));
flow+=dfs(st,inf,ed);
}
return flow;
}
void Find(int now){
vis[now]=1;
for(int i=head[now];i!=-1;i=edge[i].nexts){
Edge e=edge[i];
if(!vis[e.to] && e.cap!=e.flow) Find(e.to);
}
}
vector<int>ve;
int main(){
int t;scanf("%d",&t); int cas=1;
while(t--){
init();
int n,m,f;scanf("%d%d%d",&n,&m,&f);
int S =1,T=n+1;
for(int i=1;i<=m;i++){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c,i);
}
int ans=0;
for(int i=1;i<=f;i++){
int a,b;scanf("%d%d",&a,&b);
addedge(a,T,b,m+1);
ans+=b;
}
ans-=max_flow(S,T);
printf("Case %d: %d\n",cas++,ans);
memset(vis,0,sizeof(vis));
Find(S);
ve.clear();
for(int i=0;i<top;i+=2 ){
Edge e=edge[i];
int cnt=0;
if(vis[e.form] && !vis[e.to] && e.id<=m){// 从S集合指向T集合的边
ve.push_back(e.id);
}
}
printf("%d",ve.size());
for(int i=0;i<ve.size();i++){
printf(" %d",ve[i]);
}
puts("");
}
return 0;
}
本文介绍了一种利用最小割算法解决特定城市选择问题的方法。该问题要求玩家选择不可从首都直接到达的城市,并需要销毁某些道路以确保这些城市的隔离。文章详细解释了如何构建图模型、确定最小割及计算最佳收益。
269

被折叠的 条评论
为什么被折叠?



