hdu 5889 Barricade【最短路SPFA+最小割--------Dinic】

Barricade

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 759    Accepted Submission(s): 224

Problem Description

The empire is under attack again. The general of empire is planning to defend his castle. The land can be seen as N towns and M roads, and each road has the same length and connects two towns. The town numbered 1 is where general's castle is located, and the town numbered N is where the enemies are staying. The general supposes that the enemies would choose a shortest path. He knows his army is not ready to fight and he needs more time. Consequently he decides to put some barricades on some roads to slow down his enemies. Now, he asks you to find a way to set these barricades to make sure the enemies would meet at least one of them. Moreover, the barricade on the i-th road requires wi units of wood. Because of lacking resources, you need to use as less wood as possible.

Input

The first line of input contains an integer t, then t test cases follow.
For each test case, in the first line there are two integers N(N≤1000) and M(M≤10000).
The i-the line of the next M lines describes the i-th edge with three integers u,v and w where 0≤w≤1000 denoting an edge between u and v of barricade cost w.

Output

For each test cases, output the minimum wood cost.

Sample Input

1

4 4

1 2 1

2 4 2

3 1 3

4 3 4

Sample Output

Source

2016 ACM/ICPC Asia Regional Qingdao Online

Recommend

wange2014   |   We have carefully selected several similar problems for you:  5901 5900 5899 5898 5897 

 

 题目大意:

 有n个点,m条无向边。敌人在点n想要攻击到点1,每次敌人一定走的都是最短路,如果我们不想要敌人从n出发走到点1,去掉每一条边都有对应的权值,求这个最小权值花费。


思路:


1、因为敌人每一次走的都是最短路,那么我们首先以点n做一遍单源最短路,求出dis【】;


2、那么我们将网络建立:

①设定n为源点,设定1为汇点。

②将dis【v】==dis【u】+1的边加入到网络中,流设定为其对应的权值。


3、那么我们跑一遍最大流,根据最大流最小割定理,我们得到的最大流就是最小割,那么就是这个最小花费。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
struct node
{
    int from;
    int to;
    int w;
    int next;
}e[1500000];
int x[100000];
int y[100000];
int ww[100000];
int dis[100000];
int vis[100000];
int head[100000];
int cur[100000];
int divv[100000];
vector<int >mp[100000];
int n,m,cont,ss,tt;
void add(int from,int to,int w)
{
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont++;
}
void getmap()
{
    ss=n;
    tt=1;
    cont=0;
    memset(head,-1,sizeof(head));
    for(int i=0;i<m;i++)
    {
        int u=x[i];
        int v=y[i];
        int w=ww[i];
        if(dis[u]==dis[v]+1)
        {
            add(v,u,w);
            add(u,v,0);
        }
        if(dis[v]==dis[u]+1)
        {
            add(u,v,w);
            add(v,u,0);
        }
    }
}
void SPFA()
{
    ss=n;
    tt=1;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)dis[i]=0x3f3f3f3f;
    dis[ss]=0;
    queue<int >s;
    s.push(ss);
    while(!s.empty())
    {
        int u=s.front();
        vis[u]=0;
        s.pop();
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i];
            int w=1;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(vis[v]==0)
                {
                    vis[v]=1;
                    s.push(v);
                }
            }
        }
    }
}
int makedivv()
{
    memset(divv,0,sizeof(divv));
    divv[ss]=1;
    queue<int >s;
    s.push(ss);
    while(!s.empty())
    {
        int u=s.front();
        if(u==tt)return 1;
        s.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int w=e[i].w;
            int v=e[i].to;
            if(divv[v]==0&&w)
            {
                divv[v]=divv[u]+1;
                s.push(v);
            }
        }
    }
    return 0;
}
int Dfs(int u,int maxflow,int tt)
{
    if(u==tt)return maxflow;
    int ret=0;
    for(int &i=cur[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        int w=e[i].w;
        if(divv[v]==divv[u]+1&&w)
        {
            int f=Dfs(v,min(maxflow-ret,w),tt);
            e[i].w-=f;
            e[i^1].w+=f;
            ret+=f;
            if(ret==maxflow)return ret;
        }
    }
    return ret;
}
void Dinic()
{
    int ans=0;
    while(makedivv()==1)
    {
        memcpy(cur,head,sizeof(head));
        ans+=Dfs(ss,0x3f3f3f3f,tt);
    }
    printf("%d\n",ans);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)mp[i].clear();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&x[i],&y[i],&ww[i]);
            mp[x[i]].push_back(y[i]);
            mp[y[i]].push_back(x[i]);
        }
        SPFA();
        getmap();
        Dinic();
    }
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值