zoukankan      html  css  js  c++  java
  • JZOJ3348. 【NOI2013模拟】秘密任务

    Description

    • 给定无向图,有边权和点权,删去一条边的代价为这条边的任意一个顶点的权值,求一个最小代价的删边方案,使得1到n的在原图中的最短路都被断开。问最小代价,以及这个方案是否唯一。
    • 2 ≤ N ≤ 400, 1 ≤ M ≤ 4 00 0,1 ≤ T ≤ 5,1 ≤ Ai, c ≤ 10^9。无向图可能有重边 。

    Solution(一些很显然的东西)

    • 显然建出最短路图,然后需要将最短路图割开,裸的最小割模型,有向边就是最短路图的边,流量为两个顶点点权最小值。跑网络流即可得出最小代价。
    • 怎么知道最小割是否唯一呢?
    • 首先简化模型:一条边的流量如果为顶点点权的min的话,还要讨论顶点的点权是否一样,再看一看这条边割了没有,这么多讨论十分难做,不如将这条边拆成两条边,一条边的流量为一个点的点权。
    • 然后我们运用必割边,如果必割边的流量之和小于最大流,那么剩下的部分一定由可能割的边组成,自然就没有唯一的方案了。
    • 问题来了,什么是必割边?

    必割边(重点在这里)

    • 必割边就是任意一个最小割都存在的边。
    • 如果一条边的两个端点u,v分别能在残量网络中与S和T相连,那么这条边就是必割边。
    • 如果这条边(u,v)没有割的话,必然可以再从S到u到v到T再流一条过去,流量就会变大,就不满足最大流的性质 ,所以这条边一定是割掉了的。
    • 从S和T分别遍历一波残量网络流好了。
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define maxn 405
    #define maxm 8005
    #define maxd 1005
    #define maxt 9005
    #define inf 1e18
    #define I(i) ((i&1)?i+1:i-1)
    #define ll long long 
    using namespace std;
    
    int T,n,m,i,j,k,x,y,num;
    int em,e[maxm*2],nx[maxm*2],ls[maxt],tot[maxn],to[maxn][maxm/2];
    ll a[maxn],ec[maxm*2],to_c[maxn][maxm/2],z,dis[maxt],ans,sum;
    int t,w,d[maxd],vis[maxt],bz[maxt];
    
    void SPFA(){
    	memset(vis,0,sizeof(vis));
    	memset(dis,127,sizeof(dis));
    	t=0,w=1,d[1]=1,vis[1]=1,dis[1]=0;
    	while (t<w){
    		t=(t+1)%maxd; 
    		int x=d[t]; vis[x]=0;
    		for(int i=1;i<=tot[x];i++) {
    			int y=to[x][i];
    			if (dis[x]+to_c[x][i]<dis[y]){
    				dis[y]=dis[x]+to_c[x][i];
    				if (!vis[y]) vis[y]=1,w=(w+1)%maxd,d[w]=y;
    			}
    		}
    	}
    }
    
    void insert(int x,int y,ll z){
    	em++; e[em]=y; nx[em]=ls[x]; ls[x]=em; ec[em]=z;
    	em++; e[em]=x; nx[em]=ls[y]; ls[y]=em; ec[em]=0;
    }
    
    int BFS(int S,int T){
    	memset(dis,127,sizeof(dis));
    	t=0,w=1,d[1]=S,dis[S]=0;
    	while (t<w){
    		int x=d[++t];
    		for(int i=ls[x];i;i=nx[i]) if (dis[x]+1<dis[e[i]]&&ec[i]){
    			dis[e[i]]=dis[x]+1;
    			d[++w]=e[i];
    		}
    	}
    	return dis[T]<1e18;
    }
    
    ll dfs(int x,ll p){
    	if (x==n) return p;
    	ll res=p;
    	for(int i=ls[x];i&&res;i=nx[i]) if (dis[x]+1==dis[e[i]]&&ec[i]){
    		ll tmp=dfs(e[i],min(res,ec[i]));
    		res-=tmp;
    		ec[i]-=tmp,ec[I(i)]+=tmp;
    	}
    	return p-res;
    }
    
    ll dinic(){
    	ll ans=0;
    	while (BFS(1,n)){
    		for(ll tmp=dfs(1,inf);tmp;tmp=dfs(1,inf))
    			ans+=tmp;
    	}
    	return ans;
    }
    
    void BFS2(int S){
    	t=0,w=1,d[1]=S,bz[S]=1;
    	while (t<w){
    		int x=d[++t];
    		for(int i=ls[x];i;i=nx[i]) if (!bz[e[i]]&&ec[i]){
    			bz[e[i]]=1;
    			d[++w]=e[i];
    		}
    	}
    }
    
    void BFS3(int S){
    	t=0,w=1,d[1]=S,bz[S]=2;
    	while (t<w){
    		int x=d[++t];
    		for(int i=ls[x];i;i=nx[i]) if (!bz[e[i]]&&ec[I(i)]){
    			bz[e[i]]=2;
    			d[++w]=e[i];
    		}
    	}
    }
    
    int main(){
    	scanf("%d",&T);
    	while (T--){
    		scanf("%d%d",&n,&m);
    		for(i=1;i<n;i++) scanf("%lld",&a[i]);
    		a[n]=inf;
    		memset(tot,0,sizeof(tot));
    		for(i=1;i<=m;i++) {
    			scanf("%d%d%lld",&x,&y,&z);
    			tot[x]++,to[x][tot[x]]=y,to_c[x][tot[x]]=z;
    			tot[y]++,to[y][tot[y]]=x,to_c[y][tot[y]]=z;
    		}
    		SPFA();
    		em=0,memset(ls,0,sizeof(ls)),num=n;
    		for(i=1;i<=n;i++) for(j=1;j<=tot[i];j++){
    			k=to[i][j];
    			if (dis[i]+to_c[i][j]==dis[k]){
    				++num;
    				insert(i,num,a[i]);
    				insert(num,k,a[k]);
    			}
    		}
    		
    		ans=dinic();
    		memset(bz,0,sizeof(bz));
    		BFS2(1);
    		BFS3(n);
    		sum=0;
    		for(x=1;x<=num;x++) for(i=ls[x];i;i=nx[i]) if (i&1&&bz[x]+bz[e[i]]==3)
    			sum+=ec[i]+ec[I(i)];
    		if (sum<ans) printf("No %lld
    ",ans);
    		else printf("Yes %lld
    ",ans);
    	}
    }
    
  • 相关阅读:
    HDU 2433 Travel (最短路,BFS,变形)
    HDU 2544 最短路 (最短路,spfa)
    HDU 2063 过山车 (最大匹配,匈牙利算法)
    HDU 1150 Machine Schedule (最小覆盖,匈牙利算法)
    290 Word Pattern 单词模式
    289 Game of Life 生命的游戏
    287 Find the Duplicate Number 寻找重复数
    283 Move Zeroes 移动零
    282 Expression Add Operators 给表达式添加运算符
    279 Perfect Squares 完美平方数
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700926.html
Copyright © 2011-2022 走看看