bzoj 3258 祕密任務

http://www.elijahqi.win/archives/3689
Description
Alice聽說在一片神奇的大陸MagicLand,有一個古老的傳說……很久很久以前,那個時候 MagicStates共和國剛剛
成立。 反對新政府的勢力雖已被鎮壓,但仍然在暗地活動。這一次,情報局得到了一個令人震驚的消息,被軟禁
在首都府邸中的Frank ——著名的反對派領袖,祕密逃出首都,去往反對派的大本營。根據相關的情報,Frank計
劃通過城市之間 發達的高速公路,經過最短的路程抵達目的地。不妨將 MagicStates共和國簡化爲由N個城市,M條
高速公路構成的連通的無向圖,首都爲城市1,反對派的大本營爲城市N。每條高速公路連接兩個不同的城市,且路
程是已知的。而Frank選擇了一條從城市1到城市N的最短路徑作爲他的逃跑路線。爲了阻止Frank,共和國總統決定
在某些城市的高速公路的出入口設立檢查 點,在Frank經過檢查點時將他逮捕。舉例來說,如果有一條高速公路連
接城市u和城市v,在這條公路的城市u或城市v的出入口設立檢查點,那麼Frank經過高速公路時就會被發現。特別
的是,由於城市N實際上處在反對派的控制下,所以不能在城市N設立檢查點。然而在任何城市設立檢查點都需要一
定的費用。更具體的,若在城市 u設立k個檢查點,就要花費 Au乘以k的代價,其中Au是城市u的相關參數。值得注
意的是,這個代價與這k個檢查點具體設在哪些公路的出入口無關,於是,總統責令情報局擬定一個方案,花費最小
的代價使得無論Frank選擇哪條最短路線,都會在(除城市N以外)某個城市的高速公路出入口被發現。讀到這裏,
Alice很想知道阻止Frank所需要花費的最小代價,並且她還希 望知道最優方案是否是唯一的。只好再請你幫助她
了。注意,我們稱兩個方案不同當且僅當存在某城市k,兩種方案中在城市 k的檢查點的設置(而不僅是數目)是
不同的。
注意,輸入文件包含多組測試數據。
Input
第一行包含一個正整數T,表示有T組測試數據。
接下來依次是T組測試數據。
每組測試數據的第一行包含兩個整數N、M。
第二行包含N-1個正整數,依次表示A1,A2,…,An-1。
接下來M行,每行三個整數Ui,Vi,Ci,表示一條連接城市Ui和城市Vi的路程等於Ci的高速公路
2≤N≤400,1≤M≤4000,1≤T≤5,
1≤Ai,c≤10^9。無向圖可能有重邊。

Output
輸出T行,依次表示每組測試數據的答案。
若最優方案唯一則輸出”Yes”和最小代價,
否則輸出”No”和最小代價。字符串和整數之間請用一個空格隔開。
Sample Input
3
3 3
2 4
1 3 23
3 2 12
2 1 11
4 4
3 2 2
1 2 1
2 3 1
3 4 1
4 1 1
3 4
3 2
1 2 1
2 3 2
2 3 19
3 1 4
Sample Output
Yes 4
Yes 3
No 2
//第1組測試數據:最優方案是在城市1 設立兩個檢查點。
第2組測試數據:最優方案是城市1的高速公路( 1, 4)的出入口設立檢查點。
第3組測試數據:最優方案是在城市2設立一個檢查點,不過既可以設置在
高速公路(1, 2)的出入口,也可以設置在高速公路(2, 3)的出入口。
HINT

Source
思考了很久發現自己好像會費用流的做法

看了眼範圍 再看眼時間榜 覺得顯然不可能是費用流

然後苦思冥想 哦最小割即可

所以首先兩遍最短路 建網絡流的圖

怎麼建 拆邊然後最小割一樣因爲一條邊有兩個端點要麼選這個要麼選那個

所以就直接新建一個點 然後兩端權值分別建成g兩條邊即可

最後在殘餘網絡上跑tarjan 確定找出那些是割邊但不一定是割邊的邊 然後判斷是否唯一解

#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<algorithm>
#define ll long long
#define pa pair<ll,int>
#define mp(x,y) make_pair(x,y)
using namespace std;
inline char gc(){
	static char now[1<<16],*S,*T;
	if(T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
	return *S++;
}
inline int read(){
	int x=0,f=1;char ch=gc();
	while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
	while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
	return x*f;
}
const int N=5000;
const int M=11000;
struct node{
	int x,y,next,z;
}data[M<<1];
bool stackf[N];
int n,m,cur[N],h[N],num,cnt,s,b[N],dfn[N],low[N],q[N],top,a[N],fr[M],to[M],level[N];
inline void insert1(int x,int y,int z){
	fr[++cnt]=x;to[cnt]=y;
	data[++num].y=y;data[num].next=h[x];h[x]=num;data[num].z=z;
	data[++num].y=x;data[num].next=h[y];h[y]=num;data[num].z=0;
}
namespace build{
	struct node{
		int x,y,next,z;
	}data[M];bool flag[550];
	ll dis1[500],dis2[500];int h[500],num,tot;
	inline void init(){
		memset(h,0,sizeof(h));num=0;
	}
	inline void dijkstra1(){
		memset(dis1,0x3f,sizeof(dis1));memset(flag,0,sizeof(flag));
		priority_queue<pa,vector<pa>,greater<pa> >q;dis1[1]=0;q.push(mp(dis1[1],1));
		while(!q.empty()){
			int x=q.top().second;q.pop();if (flag[x]) continue;flag[x]=1;
			for (int i=h[x];i;i=data[i].next){
				int y=data[i].y,z=data[i].z;
				if (dis1[x]+z<dis1[y]){
					dis1[y]=dis1[x]+z;
					q.push(mp(dis1[y],y));
				}
			}
		}
	}
	inline void dijkstra2(){
		memset(dis2,0x3f,sizeof(dis2));memset(flag,0,sizeof(flag));
		priority_queue<pa,vector<pa>,greater<pa> >q;dis2[n]=0;q.push(mp(dis2[n],n));
		while(!q.empty()){
			int x=q.top().second;q.pop();if (flag[x]) continue;flag[x]=1;
			for (int i=h[x];i;i=data[i].next){
				int y=data[i].y,z=data[i].z;
				if (dis2[x]+z<dis2[y]){
					dis2[y]=dis2[x]+z;
					q.push(mp(dis2[y],y));
				}
			}
		}
	}
	inline void gao(){init();
		for (int i=1;i<=m;++i){
			int x=read(),y=read(),z=read();
			data[++num].y=y;data[num].next=h[x];h[x]=num;data[num].x=x;data[num].z=z;
			data[++num].y=x;data[num].next=h[y];h[y]=num;data[num].x=y;data[num].z=z;
		}dijkstra1();dijkstra2();ll tmp=dis1[n];tot=n;
		for (int i=1;i<=num;++i){
			int x=data[i].x,y=data[i].y,z=data[i].z;
			if (dis1[x]+dis2[y]+z==tmp){
				if (y==n) {
					insert1(x,y,a[x]);continue;
				}++tot;
				insert1(x,tot,a[x]);insert1(tot,y,a[y]);
			}
		}
	}
}
inline bool bfs(){
	queue<int>q;memset(level,0,sizeof(level));level[1]=1;q.push(1);
	while(!q.empty()){
		int x=q.front();q.pop();
		for (int i=h[x];i;i=data[i].next){
			int y=data[i].y,z=data[i].z;
			if (level[y]||!z) continue;level[y]=level[x]+1;
			if (y==n) return 1;q.push(y);
		}
	}return 0;
}
inline ll dfs(int x,ll s){
	if (x==n) return s;ll ss=s;
	for (int &i=cur[x];i;i=data[i].next){
		int y=data[i].y,z=data[i].z;
		if (level[x]+1==level[y]&&z){
			ll xx=dfs(y,min((ll)z,s));if (!xx) level[y]=0;
			s-=xx;data[i].z-=xx;data[i^1].z+=xx;
			if (!s) return ss;
		}
	}return ss-s;
}
inline void tarjan(int x){
	dfn[x]=low[x]=++num;q[++top]=x;stackf[x]=1;
	for (int i=h[x];i;i=data[i].next){
		int y=data[i].y,z=data[i].z;
		if (!z) continue;
		if (!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);else 
		if (stackf[y]) low[x]=min(low[x],dfn[y]);
	}
	if (low[x]==dfn[x]){
		++s;int y;
		do{
			y=q[top--];stackf[y]=0;b[y]=s;
		}while(y!=x);
	}
}
int main(){
	freopen("bzoj3258.in","r",stdin);
	int T=read();
	while(T--){
		n=read();m=read();
		for (int i=1;i<n;++i) a[i]=read();
		num=1;cnt=0;s=0;memset(h,0,sizeof(h));
		build::gao();ll ans=0;
		while(bfs()) memcpy(cur,h,sizeof(h)),ans+=dfs(1,1LL<<60);
		memset(dfn,0,sizeof(dfn));num=0;bool flag=1;
		for (int i=1;i<=build::tot;++i) if (!dfn[i]) tarjan(i);
		for (int i=1;i<=cnt;++i){
			if (data[i<<1].z) continue;
			if (b[fr[i]]==b[to[i]]) continue;
			if (b[fr[i]]==b[1]&&b[to[i]]==b[n]) continue;
			flag=0;break;
		}
		if (flag) printf("Yes %lld\n",ans);
		else printf("No %lld\n",ans);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章