码迷,mamicode.com
首页 > 其他好文 > 详细

There is a war (hdu 2435 最小割+枚举)

时间:2015-08-25 23:56:52      阅读:572      评论:0      收藏:0      [点我收藏+]

标签:there is a war   hdu 2435   最小割+枚举   

There is a war

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 970    Accepted Submission(s): 277


Problem Description
      There is a sea.
      There are N islands in the sea.
      There are some directional bridges connecting these islands.
      There is a country called Country One located in Island 1.
      There is another country called Country Another located in Island N. 
      There is a war against Country Another, which launched by Country One.
      There is a strategy which can help Country Another to defend this war by destroying the bridges for the purpose of making Island 1 and Island n disconnected.
      There are some different destroying costs of the bridges.
      There is a prophet in Country Another who is clever enough to find the minimum total destroying costs to achieve the strategy.
      There is an architecture in Country One who is capable enough to rebuild a bridge to make it unbeatable or build a new invincible directional bridge between any two countries from the subset of island 2 to island n-1.
      There is not enough time for Country One, so it can only build one new bridge, or rebuild one existing bridge before the Country Another starts destroying, or do nothing if happy.
      There is a problem: Country One wants to maximize the minimum total destroying costs Country Another needed to achieve the strategy by making the best choice. Then what’s the maximum possible result?
 

Input
      There are multiple cases in this problem.
      There is a line with an integer telling you the number of cases at the beginning.
      The are two numbers in the first line of every case, N(4<=N<=100) and M(0<=M<=n*(n-1)/2), indicating the number of islands and the number of bridges.
      There are M lines following, each one of which contains three integers a, b and c, with 1<=a, b<=N and 1<=c<=10000, meaning that there is a directional bridge from a to b with c being the destroying cost.
      There are no two lines containing the same a and b.
 

Output
      There is one line with one integer for each test case, telling the maximun possible result.
 

Sample Input
4 4 0 4 2 1 2 2 3 4 2 4 3 1 2 1 2 3 1 3 4 10 4 3 1 2 5 2 3 2 3 4 3
 

Sample Output
0 2 1 3
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:  2433 2432 2430 2429 2431 


题意:n个国家,m条有向边,国家1要去攻打国家n,n想切断1到n的道路来防御,切断每条道路有一定费用,国家1有一个NB魔法,可以建一条新边或者加固一条已有的边,这条边不能被n破坏,现在求 最大化n国花费之和的最小值。

思路:可知就是求最小割边集,先建图,跑一遍最大流得ans,然后从S集到T集枚举割边使容量为INF,在残留网络中再跑网络流并记录最大值Max,那么最后答案就是ans+Max。在枚举的时候也可以直接重新建图,这样应该好理解一些。

代码:

#include <iostream>
#include <functional>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

#define INF 0x3f3f3f3f
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 2005;
const int MAXM = 200010;

struct Edge
{
    int to,next,cap,flow;
}edge[MAXM],e[MAXM];

int n,m;
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN],hed[MAXN];
int S[MAXN],T[MAXN];

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}

//加边,单向图三个参数,双向图四个参数
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u];
    edge[tol].flow=0; head[u]=tol++;
    edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v];
    edge[tol].flow=0; head[v]=tol++;
}

//输入参数:起点,终点,点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end,int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u=start;
    pre[u]=-1;
    gap[0]=N;
    int ans=0;
    while (dep[start]<N)
    {
        if (u==end)
        {
            int Min=INF;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                if (Min>edge[i].cap-edge[i].flow)
                    Min=edge[i].cap-edge[i].flow;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
            {
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
            }
            u=start;
            ans+=Min;
            continue;
        }
        bool flag=false;
        int v;
        for (int i=cur[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].to;
            if (edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if (flag)
        {
            u=v;
            continue;
        }
        int Min=N;
        for (int i=head[u];i!=-1;i=edge[i].next)
            if (edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
        gap[dep[u]]--;
        if (!gap[dep[u]]) return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if (u!=start) u=edge[pre[u]^1].to;
    }
    return ans;
}

bool vis[MAXN];

void dfs(int u)
{
    vis[u]=true;
    for (int i=head[u];~i;i=edge[i].next)
    {
        int v=edge[i].to;
        if (edge[i].cap-edge[i].flow>0&&!vis[v])
            dfs(v);
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
#endif
    int i,j,t,u,v,w;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d%d",&n,&m);
        init();
        for (i=0;i<m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
        }
        int ans=sap(1,n,n);
        memset(vis,false,sizeof(vis));
        dfs(1);
        int ss=0,tt=0;
        for (i=1;i<=n;i++)
        {
            if (vis[i]) S[ss++]=i;
            else T[tt++]=i;
        }
//        printf("%d %d\n",ss,tt);
        for (i=0;i<tol;i++)
            e[i]=edge[i];
        for (i=1;i<=n;i++)
            hed[i]=head[i];
        int Max=0;
        for (i=0;i<ss;i++)
        {
            for (j=0;j<tt;j++)
            {
                for (int k=0;k<tol;k++)
                    edge[k]=e[k];
                for (int k=1;k<=n;k++)
                    head[k]=hed[k];
                if (S[i]==1||T[j]==n) continue;
                addedge(S[i],T[j],INF);
                int x=sap(1,n,n);
                Max=max(Max,x);
                tol-=2;
            }
        }
        printf("%d\n",ans+Max);
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

There is a war (hdu 2435 最小割+枚举)

标签:there is a war   hdu 2435   最小割+枚举   

原文地址:http://blog.csdn.net/u014422052/article/details/47983563

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!