poj 2455 最大流+二分

来源:互联网 发布:java输入字符串排序 编辑:程序博客网 时间:2024/05/20 06:30

题目:http://poj.org/problem?id=2455

一开始以为用矩阵 d[i][j] 可以节省时间和效率的呢,不过后来考虑到那样可能会把边搞的少了许多!!导致WA了n次。。。。

/*题目描述:题意:FJ有N块地,这些地之间有P条双向路,每条路的都有固定的长度l。现在要你找出从第1块地到第n块地的T条不同路径,每条路径上的路不能与先前的路径重复,问这些路径中的最长路的最小是多少。*/#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;#define M 4100const int inf=1<<30;int gap[M],dis[M],pre[M],cur[M];int NE,NV,sink,source,d[402][402];int head[M],n,p,ans;struct Node{    int u,v,c,pos,next;} E[999999],Edge[999999];#define FF(i,NV) for(int i=0;i<NV;i++)int sap(int s,int t){    //memset(pre,-1,sizeof(pre));    memset(dis,0,sizeof(int)*(NV+1));    memset(gap,0,sizeof(int)*(NV+1));    FF(i,NV) cur[i] = head[i];    int u = pre[s] = s,maxflow = 0,aug =inf;    gap[0] = NV;    while(dis[s] < NV)    {loop:        for(int &i = cur[u]; i != -1; i = E[i].next)        {            int v = E[i].pos;            if(E[i].c && dis[u] == dis[v] + 1)            {                aug=min(aug,E[i].c);                pre[v] = u;                u = v;                if(v == t)                {                    maxflow += aug;                    for(u = pre[u]; v != s; v = u,u = pre[u])                    {                        E[cur[u]].c -= aug;                        E[cur[u]^1].c += aug;                    }                    aug = 1<<29;                }                goto loop;            }        }        int mindis = NV;        for(int i = head[u]; i != -1 ; i = E[i].next)        {            int v = E[i].pos;            if(E[i].c && mindis > dis[v])            {                cur[u] = i;                mindis = dis[v];            }        }        if( (--gap[dis[u]]) == 0)break;        gap[ dis[u] = mindis+1 ] ++;        u = pre[u];    }    return maxflow;}void addEdge(int u,int v,int c ){    E[NE].c = c;    E[NE].pos = v;    E[NE].next = head[u];    head[u] = NE++;    E[NE].c = 0;    E[NE].pos = u;    E[NE].next = head[v];    head[v] = NE++;}int ok(int mid,int t){    int i,j;    NE=0;    memset(head,-1,sizeof(int)*(NV+1));    addEdge(source,1,t);    for(i=1; i<=p; i++)    {        if(Edge[i].c<=mid)        {            addEdge(Edge[i].u,Edge[i].v,1);            addEdge(Edge[i].v,Edge[i].u,1);        }    }    addEdge(n,sink,t);    if(sap(source,sink)>=t) return 1;    return 0;}int main(){    int i,j,a,b,c,t;    while(scanf("%d%d%d",&n,&p,&t)!=EOF)    {        source=0;        sink=n+1;        NV=sink+1;        int l=inf,r=1;        for(i=1; i<=p; i++)        {            scanf("%d%d%d",&a,&b,&c);            Edge[i].u=a;            Edge[i].v=b;            Edge[i].c=c;            r=max(c,r);            l=min(l,c);        }        int res=1;        while(l<=r)        {            int mid=(l+r)>>1;            if(ok(mid,t))            {                r=mid-1;                res=mid;            }            else l=mid+1;        }        printf("%d\n",res);    }    return 0;}/*7 9 21 2 22 3 53 7 51 4 14 3 14 5 75 7 11 6 36 7 3*/