poj2391

链接:http://poj.org/problem?id=2391

题解:

二分答案,变成判定性问题,只需把能经过的边在当前图中联通

另外对牛和牛棚要拆点

代码:

#include <cstdio>  
#include <cstring>  
#include <algorithm>  
#include <iostream>  
#include <vector>  
#include <queue>  
using namespace std;
#define ll long long
const int maxn=1e6;
const int maxn2=500;
#define INF 1e16
#define INF2 1e9
int n,m,s,t,l,sum,ax;
int head[maxn2],head2[maxn2],d[maxn2],cow[maxn2],cap[maxn2];
ll dis[maxn2][maxn2];
bool vis[maxn2];
struct re{
    int a,b,c,flow;
}a[maxn];
void arr(int x,int y,int z)
{
    a[++l].a=head[x];
    ax=max(ax,l);
  a[l].b=y;
    a[l].c=z;
    a[l].flow=0;
    head[x]=l;
}
queue<int> q;
bool bfs(){
    memset(vis,0,sizeof(vis));
    q.push(s);
    d[s]=0; vis[s]=1;
    while (!q.empty())
    {
        int x=q.front();q.pop();
        int u=head[x];
        while (u)
        {
            int v=a[u].b;
            if (!vis[v]&&a[u].c>a[u].flow)
            {
                vis[v]=1;
                d[v]=d[x]+1;
                q.push(v);
            }
            u=a[u].a;
        }
    }
    return(vis[t]);
}
int dfs(int x,int y)
{
    if (x==t||y==0) return y;
    int flow=0,f,tmp;
    int u=head[x];
    while (u)
    {
        int v=a[u].b;
        if (d[x]+1==d[v]&&(f=dfs(v,min(y,a[u].c-a[u].flow)))>0)
        {
            a[u].flow+=f;
            if (u%2) tmp=u+1; else tmp=u-1;
            a[tmp].flow-=f;
            flow+=f; 
            y-=f;
            if (y==0) break;
        }
        u=a[u].a;
    }
    head[x]=u;
    return(flow);
}
int maxflow()
{
    int flow=0;
    while (bfs())
    {
        flow+=dfs(s,INF2);
        memcpy(head,head2,sizeof(head2));
    }
    return(flow);
}
void floyd()
{
    for (int k=1;k<=n;k++)
      for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
          if (i!=j)
          dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
void buildedge(ll x)
{
  memset(head,0,sizeof(head));l=0;
    for (int i=1;i<=n;i++)
    {
        arr(0,i,cow[i]); arr(i,0,0);
        arr(i+n,n*2+1,cap[i]); arr(n*2+1,i+n,0);
        arr(i,i+n,INF2); arr(i+n,i,0);
    } 
    for (int i=1;i<=n;i++)
      for (int j=1;j<=n;j++)
        if (dis[i][j]<=x)
        {
          arr(i,j+n,INF2); arr(j+n,i,0); 
        }
}
ll solve()
{
    ll ans=-1,h=1,t=INF-1000;
    while (h<=t)
    {
        ll mid=(h+t)/2; 
        buildedge(mid); memcpy(head2,head,sizeof(head));
        if (maxflow()>=sum)
        {
            ans=mid; t=mid-1;
        } else h=mid+1;
    }
    return ans; 
}
int main()
{
    freopen("noip.in","r",stdin);
    freopen("noip.out","w",stdout);
    std::ios::sync_with_stdio(false);
    while (cin>>n>>m)
    {
        sum=0; s=0; t=2*n+1;
        for (int i=1;i<=n;i++)
        {
            cin>>cow[i]>>cap[i];
            sum+=cow[i];
        }
        for (int i=1;i<=n;i++)
          for (int j=1;j<=n;j++)
            dis[i][j]=INF;
        ll a,b,c;
        for (int i=1;i<=m;i++)
        {
            cin>>a>>b>>c;
            dis[a][b]=min(dis[a][b],c);
            dis[b][a]=min(dis[b][a],c);
        }
        floyd();
        cout<<solve()<<endl;
    } 
    return 0;
} 

 

posted @ 2018-02-10 17:03  尹吴潇  阅读(160)  评论(0编辑  收藏  举报