在一个有向图中,有n个点,m条边$n \le 1000 \And \And m \le 100000$
每条边有一个破坏的花费,有些点可以被选择并获得对应的金币。
假设一个可以选的点是$x$,你只有破坏了从1号点到$x$的路,才可以得到$x$对应的金币。
点和边的区别在于,你放弃一个点得到0,选择一个点得到val。你放弃选择一条边得到0,选择一条边得到 - val。
那么我们先把每个点的权值加到ans中,最够减去这个图的最小割即可。
由于要输出破坏边的方案,所以要dfs染色,又由于是有向边,所以破坏的边是起点属于s的边。
// #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include #include #include #include #include #include #include #include #include #include <string> #include #include #include #include #include #include #include <set> #include //#include //#include // #include // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<#define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9+7; template inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /**********showtime************/ const int maxn = 1009; int head[maxn], gtot = 0; struct Edge{ int u, v, w; int id; int nxt; } edge[300009]; void addedge(int u, int v, int w, int id) { edge[gtot].u = u; edge[gtot].v = v; edge[gtot].w = w; edge[gtot].nxt = head[u]; edge[gtot].id = id; head[u] = gtot++; edge[gtot].u = v; edge[gtot].v = u; edge[gtot].w = 0; edge[gtot].nxt = head[v]; edge[gtot].id = 0; head[v] = gtot++; } int n,m,f; vector<int>vec; int cur[maxn],dis[maxn]; bool bfs(int s, int t) { for(int i=s; i<=t; i++) { cur[i] = head[i]; dis[i] = inf; } dis[s] = 0; queue<int>que; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); for(int i=head[u]; ~i; i=edge[i].nxt) { int v = edge[i].v, w = edge[i].w; if(w > 0 && dis[v] > dis[u] + 1) { dis[v] = dis[u] + 1; que.push(v); } } } return dis[t] < inf; } int dfs(int u, int t, int maxflow) { if(u == t || maxflow == 0) return maxflow; for(int i=cur[u]; ~i; i=edge[i].nxt) { cur[u] = i; int v = edge[i].v, w = edge[i].w; if(w > 0 && dis[v] == dis[u] + 1) { int f = dfs(v, t, min(maxflow, w)); if(f > 0) { edge[i].w -= f; edge[i ^ 1].w += f; return f; } } } return 0; } int dinic(int s, int t) { int flow = 0; while(bfs(s, t)) { while(int f = dfs(s, t, inf)) flow += f; } return flow; } int col[maxn]; void colnode(int u) { col[u] = 1; for(int i=head[u]; ~i; i= edge[i].nxt) { int v = edge[i].v, w = edge[i].w; if(w && col[v] == 0) colnode(v); } } int main(){ int T; scanf("%d", &T); int cas = 0; while(T--) { scanf("%d%d%d", &n, &m, &f); int s = 0, t = n + 1; for(int i=s; i<=t; i++) head[i] = -1, col[i] = 0; gtot = 0; for(int i=1; i<=m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w, i); } int sum = 0; addedge(s, 1, inf, 0); for(int i=1; i<=f; i++) { int u, w; scanf("%d%d", &u, &w); addedge(u, t, w, 0); sum += w; } sum = sum - dinic(s, t); printf("Case %d: %d\n", ++cas, sum); colnode(s); vec.clear(); for(int i=0; i) { int u = edge[i].u, v = edge[i].v, w = edge[i].w; int id = edge[i].id; if(col[u] == 1 && col[v] == 0 && id) { vec.pb(id); } } printf("%d", vec.size()); // sort(vec.begin(), vec.end()); for(int v : vec) { printf(" %d", v); } puts(""); } return 0; }