1 5 6 2 2 1 2 2 1 3 1 1 1 2 3 1 1 2 1 2
3 0 2 1HintNo city was rebuilt in the third year,city 1 and city 3 were rebuilt in the fourth year,and city 2 was rebuilt in the sixth year.
题目:有三种操作,修城,建边,毁边。
第二第三种操作直接处理边就行。
修城操作:建立一个结点v,先dfs看这次修城可以修哪些城市,然后将这些城市与v建立容量为1,费用为0的边
对于每个修城操作的v建立s到v的边,容量为k,越后面的操作费用越低。费用最好是200的以上的,这样取模就能知道最大流是多少了
对于每个城市建立费用为0,容量为1的边到t。
费用流一遍。与s连的边的使用情况就是答案。因为后面的费用较低,所以能保证字典序最小。
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<iostream> #define maxn 1000 #define maxm 200000 #define inf 10000000 using namespace std; int head[maxn],tail; int queue[maxn],pre[maxn],flag[maxn]; int dist[maxn],maxFlow[maxn]; struct Edge{ int v,u,next,cost,w; Edge(){}//费用,权值 Edge(int u,int v,int next,int cost,int w):u(u),v(v),next(next),cost(cost),w(w){} } edge[maxm]; void add_edge(int u,int v,int cost,int w){ edge[tail] = Edge(u,v,head[u],cost,w); head[u] = tail++; edge[tail] = Edge(v,u,head[v],-cost,0); head[v] = tail++; } void init(){ memset(head,-1,sizeof(head)); tail=0; } int SPFA(int start,int end){ int i,u,v,front,rear; front = rear = 0; memset(flag,0,sizeof(flag)); memset(dist,0x1f,sizeof(dist)); memset(pre,-1,sizeof(pre)); dist[start] = 0, dist[end] = inf ,flag[start]=1; maxFlow[start] = inf, queue[rear++] = start; while(front != rear){//增广 u = queue[front++]; if(front >= maxn) front = 0; flag[u] = 0; for(i = head[u]; i!=-1;i=edge[i].next){ v=edge[i].v; if(edge[i].w&&dist[v]>dist[u]+edge[i].cost){ dist[v]=dist[u]+edge[i].cost; maxFlow[v]=min(edge[i].w,maxFlow[u]); pre[v]=i;//记录边下标 if(!flag[v]){ queue[rear++]=v; if(rear>=maxn)rear=0; flag[v] =1; } } } } return dist[end] != inf; } //开始点,结束点 int MFMC(int start,int end){ int min_cost = 0,v; while(SPFA(start,end)){ v = end; while(pre[v]>=0){ edge[pre[v]].w-=maxFlow[end]; edge[pre[v]^1].w+=maxFlow[end]; v=edge[pre[v]].u; }//跟新费用 min_cost+=dist[end]*maxFlow[end]; } return min_cost; } int map[207][207]; vector<int> stack; int check[207]; int n; void dfs(int u){ if(check[u]) return; check[u] = 1; stack.push_back(u); for(int i = 1;i <= n; i++){ if(map[u][i] == 1 && check[i] == 0){ dfs(i); } } } int main(){ int m,t,k; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&k); init(); memset(map,0,sizeof(map)); for(int i = 1;i <= n; i++) add_edge(i,n+1,1,1); int q,u,v,t,cost = n+2; for(int i = 0;i < m; i++){ scanf("%d",&t); if(t == 1){ scanf("%d",&u); memset(check,0,sizeof(check)); stack.clear(); dfs(u); add_edge(0,cost,500000-cost*500,k); for(int j = 0;j < stack.size() ;j++){ add_edge(cost,stack[j],0,1); } cost++; } else if(t == 2){ scanf("%d%d",&u,&v); map[v][u] = map[u][v] = 1; } else { scanf("%d",&q); while(q--){ scanf("%d%d",&u,&v); map[u][v] = map[v][u] = 0; } } } int ans = MFMC(0,n+1); stack.clear(); for(int i = head[0];i != -1; i=edge[i].next){ stack.push_back(k-edge[i].w); } printf("%d\n",ans%500); int flag = 0; for(int i = stack.size() - 1;i >= 0; i--){ if(i != stack.size()-1) printf(" "); printf("%d",stack[i]); } printf("\n"); } return 0; }