poj 2186 强连通分支
hdu 2256

hdu 3416 最短路+最大流

scturtle posted @ 2010年9月06日 04:04 in algorithm , 2928 阅读

求源点到终点的不共享边的最短路有多少条.

先求一次单源最短路,得到距离数组d,考虑某条边,它的起点是k1,终点是k2,边的权是c,如果d[k2]-d[k1]=c就说明这条边是最短路上的---wr大牛

原来我的想法是求一次单源最短路得到最短路长度,然后再一次求一次单源最短路并回溯来构造流网络,实在是太菜了而且流网络方面也没有想清楚......

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define maxn 1050
#define inf 0x3f3f3f3f
using namespace std;
int n,m;
struct Edge{int w,wt,next;}e[1000000];
int start[maxn];
int d[maxn];//单源距离

void spfa(int s)
{
    int i,v,N=0;
    deque<int> dq;
    for(v=0;v<n;v++)
        d[v]=inf;
    d[s]=0;
    dq.push_back(s);dq.push_back(n);
    while(!dq.empty())
    {
        v=dq.front();dq.pop_front();
        if(v==n)
        {if(N++>n) return;dq.push_back(n);}
        else
            for(i=start[v];i!=-1;i=e[i].next)
            {
                if(d[e[i].w]>d[v]+e[i].wt)
                {
                    d[e[i].w]=d[v]+e[i].wt;
                    dq.push_back(e[i].w);
                }
            }
    }
}

int flow[maxn][maxn],maxflow[maxn],father[maxn];
int Maxflow,visit[maxn];

void ford_fulkerson(int s,int t)
{
    queue<int>Q;
    int i,u,v;
    while(1)
    {
        //memset(maxflow,0,sizeof(maxflow));//每次寻找增广路径都将每个点的流入容量置为0
        //memset(visit,0,sizeof(visit));//标记一个点是否已经压入队列
        for(i=0;i<n;i++) maxflow[i]=visit[i]=0;
        maxflow[s]=inf;//源点的容量置为正无穷
        Q.push(s);// 将源点压入队列
        while(!Q.empty())
        {
            u=Q.front();
            Q.pop();
            for(v=0;v<n;v++) if(!visit[v]&&flow[u][v]>0)
            {
                visit[v]=1;
                father[v]=u;//记录下他的父亲方便往后的正反向更新
                Q.push(v);
                maxflow[v]=(maxflow[u]<flow[u][v]?maxflow[u]:flow[u][v]);//当前点的容量为父亲点容量与边流量的较小者
            }
            if(maxflow[t]>0)//如果找到了汇点并且汇点容量不为0则清空队列
            {
                while(!Q.empty())
                    Q.pop();
                break;
            }
        }
        if(maxflow[t]==0)//已经找不到到汇点的增广路经了,就退出整个循环
            break;
        for(i=t;i!=s;i=father[i])
        {
            flow[father[i]][i]-=maxflow[t];//正向更新
            flow[i][father[i]]+=maxflow[t];//反向更新
        }
        Maxflow+=maxflow[t];//更新最大流
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif

    int i,v,w,wt,s,t,cnt;
    int cas;scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        cnt=0; for(v=0;v<n;v++) start[v]=-1;
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&v,&w,&wt);
            v--;w--;
            e[cnt].w=w;e[cnt].wt=wt;
            e[cnt].next=start[v];start[v]=cnt++;
        }
        scanf("%d%d",&s,&t);
        s--;t--;
        spfa(s);

        //for(v=0;v<n;v++)
                //cout<<v<<":"<<d[v]<<" ";
        //cout<<endl;

        Maxflow=0;
        for(v=0;v<n;v++) for(w=0;w<n;w++) flow[v][w]=0;
        for(v=0;v<n;v++)
            for(i=start[v];i!=-1;i=e[i].next)
            {
                w=e[i].w;
                if(d[w]-d[v]==e[i].wt)
                    flow[v][w]+=1;
            }
        ford_fulkerson(s,t);
        printf("%d\n",Maxflow);
    }
}
Trinity 说:
2011年7月17日 23:10

果断膜拜玩再走,我原来的方法果断超时,YM,膜拜


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter