HLG 1512 March of the Penguins

题意 : 已知有n 个浮冰 ,和每个企鹅可以跳跃的最大距离,知道了每个浮冰的坐标,和该浮冰上一开始有的企鹅数量,和 该浮冰最多能承受的跳跃次数,跳跃次数是指从该浮冰跳出的最大次数,浮冰的编号从 0 开始, 里面哪些浮冰满足 最后所有的企鹅都能够到达。

分析: 建立一个超级 源点 s=0 ,将每个浮冰分成两个点,左边的点记为 1..n ,右面的点依次为 n+1..n+n,在浮冰 i 和 i+n 之间连一条从i 到 i+n 的边,容量设为 浮冰 i 上的

         最大跳跃次数,在源点 s 和 每块冰 i(1..n)之间连一条从 s 到 i 的边,容量设为冰 i 上初始的企鹅数量,即为该点的初始流量,如果 冰 i 和 冰 j 的距离小于等于企鹅可以跳跃的最大距离,即可以从 i 跳到 j,也可以从j 跳到 i ,在 冰 i+n 和冰 j 之间连一条容量为 INF 的边,因为冰 j 的跳入次数没有限制,所以容量为无穷大,在 j+n和i 之间也连一条同样的边, 最后分别以 冰(1..n)为汇点求最大流,如果最大流为 企鹅数量 M ,则该浮冰就可以作为最终的落脚点。

 邻接矩阵:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define INF 0x1f1f1f1f
#define min(a,b)(a)<(b)?(a):(b)
#define clr(x)memset(x,0,sizeof(x))
int c[202][202];
int gap[202];
int dis[202];
void init(int s,int u,int n)
{
    int v,x,front=0,rear=0;
    int q[203];
    clr(gap);
    memset(dis,0xff,sizeof(dis));
    q[rear++]=u;
    dis[u]=0;
    while(front<rear)
    {
        x=q[front++];
        gap[dis[x]]++;
        for(v=0;v<=n;v++)
            if(dis[v]==-1&&c[v][x]>0)
            {
                dis[v]=dis[x]+1;
                q[rear++]=v;
            }
    }
}
int sap(int s,int u,int n)
{
    init(s,u,n);
    int flag,flow=0,top=s,i,j,k;
    int pre[203],low[203];
    clr(low);
    while(dis[s]<=n)
    {
        flag=0;
        low[s]=INF;
        for(i=0;i<=n;i++)
            if(c[top][i]>0&&dis[top]==dis[i]+1&&dis[i]>=0)
            {
                flag=1;
                break;
            }
        if(flag)
        {
            low[i]=c[top][i];
            low[i]=min(low[i],low[top]);
            pre[i]=top;
            top=i;
            if(top==u)
            {
                flow+=low[u];
                j=top;
                while(j!=s)
                {
                    k=pre[j];
                    c[k][j]-=low[u];
                    c[j][k]+=low[u];
                    j=k;
                }
                top=s;
                clr(low);
            }
        }
        else
        {
            int dmin=n;
            for(j=0;j<=n;j++)
                if(c[top][j]>0&&dis[j]+1<dmin&&dis[j]>=0)
                    dmin=dis[j]+1;
            gap[dis[top]]--;
            if(gap[dis[top]]==0)
                break;
            gap[dmin]++;
            dis[top]=dmin;
            if(top!=s)
                top=pre[top];
        }
    }
    return flow;
}
struct node
{
    double x,y;
    int num,ti;
}pe[102];
double dist(node a,node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
struct edge
{
    int from,to,flow;
}e[1000000];
int tot;
void add(int s,int u,int f)
{
    e[tot].from=s;
    e[tot].to=u;
    e[tot++].flow=f;
}
int res[102];
int main()
{
//    freopen("D:ce.txt","r",stdin);
    int t,n,i,j,top,max_flow,pe_num;
    double d;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%lf",&n,&d);
        clr(c);
        tot=0;
        pe_num=0;
        for(i=1;i<=n;i++)
            scanf("%lf%lf%d%d",&pe[i].x,&pe[i].y,&pe[i].num,&pe[i].ti);
        for(i=1;i<=n;i++)
            if(pe[i].num)
            {
                pe_num+=pe[i].num;
                c[0][i]=pe[i].num;
                add(0,i,pe[i].num);
            }
        for(i=1;i<=n;i++)
            if(pe[i].ti)
            {
                c[i][i+n]=pe[i].ti;
                add(i,i+n,pe[i].ti);
            }
        for(i=1;i<n;i++)
            for(j=i+1;j<=n;j++)
                if(dist(pe[i],pe[j])<=d)
                {
                    c[i+n][j]=INF;
                    c[j+n][i]=INF;
                    add(i+n,j,INF);
                    add(j+n,i,INF);
                }
        top=0;
        for(i=1;i<=n;i++)
        {
            max_flow=sap(0,i,2*n);
            if(max_flow==pe_num)
                res[top++]=i-1;
            for(j=0;j<tot;j++)
            {
                c[e[j].from][e[j].to]=e[j].flow;
                c[e[j].to][e[j].from]=0;
            }
        }
        if(top)
        {
            for(i=0;i<top;i++)
                printf("%d%c",res[i],i==top-1?'\n':' ');
        }
        else
            printf("-1\n");
    }
    return 0;
}

 

 前向星:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define min(a,b)(a)<(b)?(a):(b)
const int INF=0x1f1f1f1f;
const double eps=1e-8;
const int maxn=222;
const int maxm=1000003;
struct node
{
    int c,next,to;
}e[maxm];
int tot;
int head[maxn];
void add(int s,int u,int flow)
{
    e[tot].to=u;
    e[tot].c=flow;
    e[tot].next=head[s];
    head[s]=tot++;
}
int max_flow(int st,int end,int n)
{
    int numh[maxn],h[maxn],curedge[maxn],pre[maxn];
    int cur_flow,maxflow=0,u,tmp,neck,i;
    memset(h,0,sizeof(h));
    memset(numh,0,sizeof(numh));
    memset(pre,0xff,sizeof(pre));
    for(i=0;i<=n;i++)
        curedge[i]=head[i];
    numh[0]=n+1;
    u=st;
    while(h[st]<n+1)
    {
        if(u==end)
        {
            cur_flow=INF;
            for(i=st;i!=end;i=e[curedge[i]].to)
                if(cur_flow>e[curedge[i]].c)
                {
                    neck=i;
                    cur_flow=e[curedge[i]].c;
                }
            for(i=st;i!=end;i=e[curedge[i]].to)
            {
                tmp=curedge[i];
                e[tmp].c-=cur_flow;
                e[tmp^1].c+=cur_flow;
            }
            maxflow+=cur_flow;
            u=neck;
        }
        for(i=curedge[u];i!=-1;i=e[i].next)
            if(e[i].c&&h[u]==h[e[i].to]+1)
                break;
        if(i!=-1)
        {
            curedge[u]=i;
            pre[e[i].to]=u;
            u=e[i].to;
        }
        else
        {
            if(--numh[h[u]]==0) break;
            curedge[u]=head[u];
            for(tmp=n,i=head[u];i!=-1;i=e[i].next)
                if(e[i].c)
                    tmp=min(tmp,h[e[i].to]);
            h[u]=tmp+1;
            ++numh[h[u]];
            if(u!=st)
                u=pre[u];
        }
    }
    return maxflow;
}
struct point
{
    double x,y;
    int in,ti;
}p[103];
double di(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int res[103];
struct tm
{
    int ii,fo;
}tp[1000000];
int main()
{
    int n,a,b,w,i,s,j,t,ff,tt,sum,tr;
    double dd;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%lf",&n,&dd);
        tot=0;
        memset(head,-1,sizeof(head));
        tr=0;
        tt=0;
        sum=0;
        for(i=1;i<=n;i++)
        {
            scanf("%lf%lf%d%d",&p[i].x,&p[i].y,&p[i].in,&p[i].ti);
            sum+=p[i].in;
        }
        s=0;
        for(i=1;i<=n;i++)
        {
            add(s,i,p[i].in);
            tp[tr].ii=tot-1;
            tp[tr++].fo=p[i].in;
            
            add(i,s,0);
            tp[tr].ii=tot-1;
            tp[tr++].fo=0;
                
        }
        for(i=1;i<=n;i++)
        {
            add(i,i+n,p[i].ti);
            tp[tr].ii=tot-1;
            tp[tr++].fo=p[i].ti;
            
            add(i+n,i,0);
            tp[tr].ii=tot-1;
            tp[tr++].fo=0;
        }
        for(i=1;i<=n;i++)
            for(j=i+1;j<=n;j++)
                if(di(p[i],p[j])<=dd+eps)
                {
                    add(i+n,j,INF);
                    tp[tr].ii=tot-1;
                    tp[tr++].fo=INF;

                    add(j,i+n,0);
                    tp[tr].ii=tot-1;
                    tp[tr++].fo=0;

                    add(j+n,i,INF);
                    tp[tr].ii=tot-1;
                    tp[tr++].fo=INF;

                    add(i,j+n,0);
                    tp[tr].ii=tot-1;
                    tp[tr++].fo=0;
                }
        for(i=1;i<=n;i++)
        {
            ff=max_flow(0,i,2*n);
            if(ff==sum)
                res[tt++]=i-1;
            for(j=0;j<tr;j++)     // 恢复原本的容量
                e[tp[j].ii].c=tp[j].fo;
        }
        if(tt)
        {
            for(i=0;i<tt;i++)
                printf("%d%c",res[i],i==tt-1?'\n':' ');
        }
        else printf("-1\n");
    }
    return 0;
}

 

posted @ 2012-08-05 20:26  'wind  阅读(264)  评论(0编辑  收藏  举报