『HDU 5889』Barricade

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5889

题意:
就是有2个城堡,1为A城堡, N为B敌人, 敌人要攻打A城堡,但我们知道敌人必定走 最短路,A城堡国王想设置障碍在这些最短路中,而且要使这些敌人必须经过1个障碍.可是现在是打仗时候,要尽量少用材料,
设置一个路障的花费为这段路的权值,求最少花费.
个人感想:
咋眼一看,咦这不是费用流吗.最大流,最小费用.我一开始看起来觉得没错啊,可是认真想了一想,肯定错的啊,因为最大流并不保证流的就是最短路径啊.而且人家都说了,他只会走最短路…那的怎么做啊?我也不太懂…
然后我看了下好多网上的题解,其实都是从原图中抽取最短路再跑最大流==最小割就好了,这又怎么抽啊,我一直都忽略的一个思想:可以通过dijkastra写好的dis数组来找到对应的路.因为我们就是从这些最短路中转移过来的,那么肯定绝对能找回原来的路径…至于大流吗,想想都知道就是把路不让他连通就好了,刚好久是最小割..
这题好有意思啊…涨姿势了…

分析:最短路+最大流

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }
 int T;
 int N,M;
 struct edge
 {
     int to;//到的节点
     int d;
     int cost;//花费
 };
 struct Edge
 {
     int to;
     int cap;
     int rev;
 };
 typedef pair<int,int> P;
 vector<edge> G[1005];
 vector<Edge> p2[1005];
 int dis[1005];
 int level[1005];
 int iter[1005];
 bool vis[1005];


 void addedge(int u,int v,int cost)
 {
      edge tmp;

      tmp.to=v;
      tmp.d=1;
      tmp.cost=cost;
      G[u].push_back(tmp);

      tmp.to=u;
      tmp.d=1;
      tmp.cost=cost;
      G[v].push_back(tmp);
 }
 void dijkastra(int s)
 {
     priority_queue<P,vector<P>,greater<P> >que;

     memset(dis,0x3f,sizeof(dis));
     dis[s]=0;
     que.push(P(0,s));
     while(!que.empty())
     {
         P p=que.top();
         que.pop();
         int v=p.second;
         if(dis[v]<p.first) continue;

         for(int i=0;i<G[v].size();i++)
         {
             edge e=G[v][i];
             //cout<<v<<"->"<<e.to<<endl;
             if(dis[e.to]>dis[v]+e.d)
             {
                 dis[e.to]=dis[v]+e.d;
                 que.push(P(dis[e.to],e.to));
             }

         }
     }

 }




 void add_edge(int from,int to,int cap)
 {
    // cout<<from<<"->"<<to<<"  "<<cap<<endl;
     p2[from].push_back((Edge){to,cap,p2[to].size()});
     p2[to].push_back((Edge){from,0,p2[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 v=que.front();
         que.pop();
         for(int i=0;i<p2[v].size();i++)
         {
             Edge &e=p2[v][i];
             if(e.cap>0 && level[e.to]<0)
             {
                 level[e.to]=level[v]+1;
                 que.push(e.to);
             }
         }
     }
 }

 int dfs(int v,int t,int f)
 {
     if(v==t) return f;
     for(int &i=iter[v];i<p2[v].size();i++)
     {
         Edge &e=p2[v][i];
         if(e.cap>0&&level[v]<level[e.to])
         {
             int d=dfs(e.to,t,min(f,e.cap));
             if(d>0)
             {
                 e.cap-=d;
                 p2[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]<0)return flow;
         memset(iter,0,sizeof(iter));
         int f;
         while((f=dfs(s,t,INF))>0)
         {
             flow+=f;
         }
     }
     return flow;
 }
int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt","r",stdin);
    freopen("lala.txt","w",stdout);
#endif
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        for(int i=0;i<=N;i++) {G[i].clear();p2[i].clear();}

        for(int i=0;i<M;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            addedge(x,y,z);
        }

        dijkastra(N);

        memset(vis,0,sizeof(vis));
        queue<int> que;
        que.push(1);
        vis[1]=true;
        while(!que.empty())
        {

            int s=que.front();
            que.pop();

            for(int j=0;j<G[s].size();j++)
            {
                edge &e=G[s][j];
                int son=e.to;
                if(dis[s]-1==dis[son])
                {
                    if(!vis[son])
                    {
                        que.push(son);
                        vis[son]=true;
                    }

                    add_edge(s,son,e.cost);

                }

            }

        }
        printf("%d\n",max_flow(1,N));

    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值