【HDU5889】Barricade(最短路+最小割)

来源:互联网 发布:linux 高性能c日志库 编辑:程序博客网 时间:2024/04/25 05:25

记录一个菜逼的成长。。

题目大意:
给你N个点,M条边。让你在每条最短路上设置至少一个障碍使得路无法通过,每一个障碍需要Wi个木材,求需要最少的木材。

显然只要每条最短路设置一个障碍,只要求最短路的最小割即可。
直接套模板。。

#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <iostream>#include <cstring>#include <string>#include <algorithm>#include <cstdlib>#include <vector>#include <set>#include <map>#include <queue>#include <stack>#include <list>#include <deque>#include <cctype>#include <bitset>#include <cmath>using namespace std;#define ALL(v) (v).begin(),(v).end()#define cl(a,b) memset(a,b,sizeof(a))#define bp __builtin_popcount#define pb push_back#define fin freopen("D://in.txt","r",stdin)#define fout freopen("D://out.txt","w",stdout)#define lson t<<1,l,mid#define rson t<<1|1,mid+1,r#define seglen (node[t].r-node[t].l+1)#define pi 3.1415926#define exp  2.718281828459typedef long long LL;typedef unsigned long long ULL;typedef pair<int,int> PII;typedef pair<LL,LL> PLL;typedef vector<PII> VPII;const int INF = 0x3f3f3f3f;const int MOD = 1e9 + 7;template <typename T>inline void read(T &x){    T ans=0;    char last=' ',ch=getchar();    while(ch<'0' || ch>'9')last=ch,ch=getchar();    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();    if(last=='-')ans=-ans;    x = ans;}inline bool DBread(double &num){    char in;double Dec=0.1;    bool IsN=false,IsD=false;    in=getchar();    if(in==EOF) return false;    while(in!='-'&&in!='.'&&(in<'0'||in>'9'))        in=getchar();    if(in=='-'){IsN=true;num=0;}    else if(in=='.'){IsD=true;num=0;}    else num=in-'0';    if(!IsD){        while(in=getchar(),in>='0'&&in<='9'){            num*=10;num+=in-'0';}    }    if(in!='.'){        if(IsN) num=-num;            return true;    }else{        while(in=getchar(),in>='0'&&in<='9'){                num+=Dec*(in-'0');Dec*=0.1;        }    }    if(IsN) num=-num;    return true;}template <typename T>inline void write(T a) {    if(a < 0) { putchar('-'); a = -a; }    if(a >= 10) write(a / 10);    putchar(a % 10 + '0');}/******************head***********************/const int maxn = 1000 + 10;const int MAX_V = maxn;int g[maxn][maxn],val[maxn][maxn];int dis[maxn],vis[maxn];//dijkstravoid init(int n){    memset(vis,0,sizeof(vis));    for(int i=1;i<=n;i++){        for(int j=1;j<=n;j++){            g[i][j]=INF;        }        dis[i]=INF;    }}void dijkstra(int s,int n){    dis[s]=0;    for(int i=1;i<n;i++){        int mn=INF,x;        for(int j=1;j<=n;j++){            if(!vis[j]&&dis[j]<mn)mn=dis[x=j];        }        vis[x]=1;        for(int j=1;j<=n;j++){            dis[j]=min(dis[j],dis[x]+g[x][j]);        }    }}//Dinic求最大流,最大流等同最小割。struct edge{    int to,cap,rev;    edge(){}    edge(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){}};vector<edge>G[MAX_V];int level[MAX_V];int iter[MAX_V];void add(int from,int to,int cap){    G[from].push_back(edge(to,cap,G[to].size()));    G[to].push_back(edge(from,0,G[from].size()-1));}void bfs(int s){    memset(level,-1,sizeof(level));    queue<int>que;    level[s] = 0;    que.push(s);    while(!que.empty()){        int f = que.front();        que.pop();        for( int i = 0; i < G[f].size(); i++ ){            edge &e = G[f][i];            if(e.cap > 0 && level[e.to] == -1){                level[e.to] = level[f] + 1;                que.push(e.to);            }        }    }}int dfs(int v,int t,int f){    if(v == t)return f;    for( int &i = iter[v]; i < G[v].size(); i++ ){        edge &e = G[v][i];        if(e.cap > 0 && level[v] < level[e.to]){            int d = dfs(e.to,t,min(e.cap,f));            if(d > 0){                e.cap -= d;                G[e.to][e.rev].cap += d;                return d;            }        }    }    return 0;}int max_flow(int s,int t){    int flow = 0;    for(;;){        bfs(s);        if(level[t] == -1)return flow;        memset(iter,0,sizeof(iter));        int f;        while((f = dfs(s,t,INF)) > 0)            flow += f;    }}int main(){    int T;scanf("%d",&T);    while(T--){        int n,m;        scanf("%d%d",&n,&m);        init(n);        for( int i = 1; i <= n; i++ )G[i].clear();        for( int w,u,v,i = 0; i < m; i++ ){            scanf("%d%d%d",&u,&v,&w);            g[u][v] = 1;            g[v][u] = 1;            val[u][v] = w;            val[v][u] = w;        }        dijkstra(1,n);        for( int i = 1; i <= n; i++ ){            for( int j = 1; j <= n; j++ ){                //判断(i,j)这条边是否是在最短路中                if(g[i][j] == 1 && dis[i] + 1 == dis[j]){                    add(i,j,val[i][j]);                }            }        }        printf("%d\n",max_flow(1,n));    }    return 0;}
0 0
原创粉丝点击