hdu 6582 path (minimum cut shortest +)

Topic links: http://acm.hdu.edu.cn/showproblem.php?pid=6582

 

The meaning of problems: there are n points, weighted uni m edges, as a starting point, end point n, the shortest output if the start is not 0, and now wants to block some of the road, so that the shortest value after the large block, or does not exist. Dulu that spend edge weights, ask minimum cost.

 

Ideas: Find the shortest side of the core, and then re-build the side, run again cut to a minimum. To find the shortest side of the core to build the forward edge of each dot to find the distance to the starting point (assumed to be d [i]), and then build the reverse side to find the distance of each point to the end point (assumed to be d2 [i]), if an edge starting point for u, end point v, the right side of w, when d [u] + d2 [v] + w == d [n] is the core of which is a shortest side.

Code:

#include<iostream>
#include<cstdio>
#include<cstring> 
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=20100;
const int maxm=20100;
const ll inf=1e18;
struct node{
    int u,v,nxt;
    ll w;
}e[2*maxm],e2[2*maxm],e3[2*maxm];
int h[maxn],h2[maxn],h3[maxn],depth[maxn];
ll d[maxn],d2[maxn];
bool vis[maxn];
int n,m,st,ed,cnt,cnt2,cnt3;

void init()
{
    memset(h,-1,sizeof(h));
    memset(h2,-1,sizeof(h2));
    memset(h3,-1,sizeof(h3));
    for(int i=0;i<=n;i++)
        d[i]=d2[i]=inf;
    cnt=cnt2=cnt3=0;
}

void add(int u,int v,ll w)//正向建边 
{
    e[cnt].u=u,e[cnt].v=v,e[cnt].w=w;
    e[cnt].nxt=h[u];h[u]=cnt++;
}

void add2(int u,int v,ll w)//反向建边 
{
    e2[cnt2].u=u,e2[cnt2].v=v,e2[cnt2].w=w;
    e2[cnt2].nxt=h2[u],h2[u]=cnt2++;
}
void add3(int u,int v,ll w)//重新建边 
{
    e3[cnt3].u=u,e3[cnt3].v=v,e3[cnt3].w=w;
    E3 [CNT3] .nxt= H3 [U], H3 [U] = CNT3 ++ ; 
} 

BOOL SPFA () // shortest distance from each point to the one of 
{ 
    Queue < int > Q; 
    Memset (VIS, 0 , the sizeof (VIS)); 
    D [ST ] = 0 ; 
    VIS [ST] = . 1 ; 
    q.push (ST); 
    the while (! q.empty ()) 
    { 
        int U = q.front (); q.pop (); 
        VIS [U] = 0 ;
         for ( int I = H [U]; I = -! . 1 ; I =E [I] .nxt) 
        { 
            int V = E [I] .v; 
            LL W = E [I] .W;
             IF (D [V]> D [U] + W) 
            { 
                D [V] = D [ U] + W;
                 IF (! VIS [V]) 
                { 
                    VIS [V] = . 1 ; 
                    q.push (V); 
                } 
            } 
        } 
    } 
    return D [n-] == INF; 
} 

void re_spfa () // find each the shortest distance to the point n 
{ 
    Queue < int > Q;
    memset(vis,0,sizeof(vis));
    d2[ed]=0;
    vis[ed]=1;
    q.push(ed);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        vis[u]=0;
        for(int i=h2[u];i!=-1;i=e2[i].nxt)
        {
            int v=e2[i].v;
            ll  w=e2[i].w;
            if(d2[v]>d2[u]+w)
            {
                d2[v]=d2[u]+w;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
  
void create_map()//重新建边 
{
    for(int i=0;i<cnt;i++)
    {
        int u=e[i].u;
        int v=e[i].v;
        ll  w=e[i].w;
        if((d[u]+d2[v]+w==d[ed])&&(d[u]<inf&&d2[v]<inf))
        {//最短路核心边 
            add3(u,v,w);
            add3(v,u,0); 
        }
    }
}

bool bfs(){//dinic分层 
    queue<int> que;
    memset(depth,0,sizeof(depth));
    que.push(st);
    depth[st]=1;
    while(!que.empty()){
        int u=que.front();
        que.pop();
        if(u==ed)
            return true;
        for(int i=h3[u];i!=-1;i=e3[i].nxt){
            int v=e3[i].v;
            ll  w=e3[i].w;
            if(!depth[v]&&w){
                depth[v]=depth[u]+1;
                que.push(v);
            }
        }
    }
    return false;
}

ll dfs(int u,ll dis)
{
    if(u==ed)
        return dis;
    ll res=0;
    for(int i=h3[u];i!=-1;i=e3[i].nxt)
    {
        int v=e3[i].v;
        ll  w=e3[i].w;
        if((depth[v]==depth[u]+1)&&w)
        {
            ll di=dfs(v,min(w,dis-res));
            e3[i].w-=di;
            e3[i^1].w+=di;
            res+=di;
            if(res==dis)
                return dis;
        }
    }
    return res;
}

void dinic()//dinic求最小割 
{
    ll ans=0;
    while(bfs())
    {
        ans+=dfs(st,inf);
    }
    printf("%lld\n",ans);
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        st=1,ed=n;
        init();
        for(int i=0;i<m;i++)
        {
            int u,v;ll w;
            scanf("%d%d%lld",&u,&v,&w);
            add(u,v,w);
            add2(v,u,w);
        }
        if(spfa())//特判,没有最短路 
            printf("0\n");
        else
        {
            re_spfa();
            create_map();
            dinic();
        }    
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/xiongtao/p/11248452.html