zoukankan      html  css  js  c++  java
  • [BZOJ1339] [Baltic2008] Mafia / 黑手党

    Description

    匪徒准备从一个车站转移毒品到另一个车站,警方准备进行布控. 对于每个车站进行布控都需要一定的代价,

    现在警方希望使用最小的代价控制一些车站,使得去掉这些车站后,匪徒无法从原定的初始点到达目标点

    Input

    第一行输入N,M代表车站的总个数,及有多少条双向边连接它们

    第二行给出两个数a,b,代表匪徒的出发点及目标点.1<=a,b<=N,a<>b.

    再下来有N行,给出对第i个车站进行布控所需要的Money,其不超过10 000 000

    再下来M行,用于描述图的结构.

    2<=n<=200 , 1 <=m<=20000

    Output

    最少需要多少Money

    Sample Input

    5 6
    5 3
    2
    4
    8
    3
    10
    1 5
    1 2
    2 4
    4 5
    2 3
    3 4
    

    Sample Output

    5
    

    Solution

    直接拆点跑最小割就好了。

    (luogu)还要输出最小割的一种方案,那么可以从(s)开始(bfs),沿着没流满的路径走,顺便走到的点标上(visited),若一条边起点被访问过,终点没有,那么这条边就被割掉了,具体可以考虑下为什么最大流等于最小割。

    这里附上求方案的版本。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 2e5+10;
    const int inf = 1e9;
    
    int n,m,s,t,tot=1;
    int head[maxn],dis[maxn];
    struct edge{int to,nxt,w;}e[maxn<<1];
    
    void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}
    void ins(int u,int v,int w) {add(u,v,w),add(v,u,0);}
    
    int bfs() {
    	memset(dis,-1,sizeof dis);
    	queue<int > q;q.push(s);dis[s]=0;
    	while(!q.empty()) {
    		int x=q.front();q.pop();
    		for(int i=head[x];i;i=e[i].nxt)
    			if(e[i].w>0&&dis[e[i].to]==-1) {
    				dis[e[i].to]=dis[x]+1;
    				if(e[i].to==t) return 1;
    				q.push(e[i].to);
    			}
    	}
    	return 0;
    }
    
    int dfs(int x,int f) {
    	if(x==t) return f;
    	int used=0;
    	for(int i=head[x];i;i=e[i].nxt)
    		if(e[i].w>0&&dis[e[i].to]==dis[x]+1) {
    			int d=dfs(e[i].to,min(f-used,e[i].w));
    			if(d>0) e[i].w-=d,e[i^1].w+=d,used+=d;
    			if(used==f) break;
    		}
    	dis[x]=-1;return used;
    }
    
    int max_flow() {
    	int flow=0;
    	for(;bfs();flow+=dfs(s,inf));
    	return flow;
    }
    
    int vis[maxn];
    
    void solve() {
    	queue<int > q;q.push(s);vis[s]=1;
    	while(!q.empty()) {
    		int x=q.front();q.pop();//write(x);
    		for(int i=head[x];i;i=e[i].nxt)
    			if(e[i].w>0&&!vis[e[i].to]) q.push(e[i].to),vis[e[i].to]=1;
    	}
    	for(int i=2;i<=tot;i+=2) if(vis[e[i^1].to]&&!vis[e[i].to]) printf("%d ",e[i^1].to);puts("");
    }
    
    int main() {
    	read(n),read(m),read(s),read(t);t+=n;
    	for(int i=1,x;i<=n;i++) read(x),ins(i,i+n,x);
    	for(int i=1,x,y;i<=m;i++) read(x),read(y),ins(x+n,y,inf),ins(y+n,x,inf);
    	max_flow();solve();
    	return 0;
    }
    
  • 相关阅读:
    HZNU Personal Training 2
    6月30日-助教题解-刺客信条起源
    Educational Codeforces Round 90 (Rated for Div. 2)
    暑假python学习笔记
    HZNU Training 32 for Zhejiang Provincial Competition 2020
    哈夫曼树
    网络流24题
    splay
    生成树计数
    HZNU Training 29 for Zhejiang Provincial Competition 2020
  • 原文地址:https://www.cnblogs.com/hbyer/p/10467114.html
Copyright © 2011-2022 走看看