Path

Path

题解

一道很明显的网络流。

由于题目只想让最小路径变大一点,所以我们可以把所有最短路径建成一张网络,然后,我们就可以找出这个图的最小割。

很显然,最小割的值就是我们总共封路的花费。

注意要开long long,笔者因为这个WA了好久。

如果打的dijk要加堆优化,否则会TLE。

源码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define MAXN 200005
using namespace std;
typedef long long LL;
#define gc() getchar()
const LL INF=0x7f7f7f7f7f7f;
int tot,head[MAXN],n,m;
int from[MAXN<<1],to[MAXN<<1];
int nxt[MAXN<<1],s,t;
LL paid[MAXN<<1];
struct ming{
	int v;LL w;
	ming(){
		v=w=0;
	}
	ming(int V,LL W){
		v=V;w=W;
	}
};
vector<ming> G[MAXN],B[MAXN];
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=gc();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
	while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
	x*=f;
} 
void addEdge(int u,int v,int w){
	from[++tot]=u;to[tot]=v;paid[tot]=w;
	nxt[tot]=head[u];head[u]=tot;
}
void addedge(int u,int v,int w){
	addEdge(u,v,w);
	addEdge(v,u,0);
}
queue<int> q;
int d[MAXN];
bool bfs(){
	memset(d,0,sizeof(d));
	while(!q.empty()) q.pop();
	q.push(s);d[s]=1;
	while(!q.empty()){
		int u=q.front();q.pop();
		if(u==t) return true;
		for(int i=head[u];~i;i=nxt[i]){
			int v=to[i];
			if(!d[v]&&paid[i]>0) 
				d[v]=d[u]+1,q.push(v);
		}
	}
	return false;
}
LL dfs(int u,LL flow){
	if(u==t||!flow) return flow;
	LL tmp=0;
	for(int i=head[u];~i;i=nxt[i]){
		int v=to[i];
		if(d[v]==d[u]+1&&paid[i]>0){
			LL now_flow=dfs(v,min(flow,paid[i]));
			paid[i]-=now_flow;paid[i^1]+=now_flow;
			flow-=now_flow;tmp+=now_flow;
			if(flow+tmp==now_flow){
				return flow+tmp;
			}
			if(!flow) break;
		}
	}
	if(!tmp) d[u]=0;
	return tmp;
}
LL dinic(){
	LL res=0;
	while(bfs()) 
		res+=dfs(s,INF);
	return res;
}
LL dis[MAXN];
bool vis[MAXN];
queue<int> q1;
typedef pair<LL,int> pii;
priority_queue<pii,vector<pii>,greater<pii> >qq;
void dijk(){
	for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=0;
	while(!qq.empty()) qq.pop();
	dis[1]=0;qq.push(make_pair(0,s));
	while(!qq.empty()){
		int k=qq.top().second;qq.pop();
		if(vis[k]) continue;
		vis[k]=true;int siz=G[k].size();
		for(int j=0;j<siz;j++){
			if(dis[G[k][j].v]>dis[k]+G[k][j].w){
				dis[G[k][j].v]=dis[k]+G[k][j].w;
				qq.push(make_pair(dis[G[k][j].v],G[k][j].v));
			}
		}
	}
}
bool inque[MAXN];
void init(){
	for(int i=1;i<=n;i++) inque[i]=false;
	while(!q1.empty()) q1.pop();
	q1.push(n);inque[n]=true;
	while(!q1.empty()){
		int u=q1.front();q1.pop();
		int siz=B[u].size();
		for(int i=0;i<siz;i++){
			if(dis[B[u][i].v]+B[u][i].w==dis[u]){
				addedge(B[u][i].v,u,B[u][i].w);
				if(inque[B[u][i].v]) continue;
				q1.push(B[u][i].v);inque[B[u][i].v]=true;
			}
		}
	}
}
int main() {
	int tt;read(tt);
	while(tt--){
		tot=-1;memset(head,-1,sizeof(head));
		read(n);read(m);s=1;t=n;
		for(int i=1;i<=m;i++){
			int u,v;LL w;read(u);read(v);read(w);
			G[u].push_back(ming(v,w));
			B[v].push_back(ming(u,w));
		}
		dijk();
		if(dis[n]<INF-1) init(),printf("%lld\n",dinic());
		else puts("0");
		for(int i=1;i<=n;i++)G[i].clear(),B[i].clear();
	}
    return 0;
}

谢谢!!!

posted @ 2019-12-11 15:22  StaroForgin  阅读(15)  评论(0)    收藏  举报  来源