Codeforces 78E Evacuation

構圖的思路與POJ 2391是一樣的,對於從一個初級源點s出發的流,如果可到達的點是受限制的,可以先把這些受限制的點都找出來,拆點拆成i->i',然後,s向i'連邊,

最後,超級源點S向每個初級源點s連邊,每個點i'向匯點連邊


爲什麼要這麼做?因爲既然從s出發的流是受限制的,我們可以在s上限制它,但也必須在每個s可到的點上限制它,而網絡流中是不分這部分流是從哪個源點過來的,因此,無法在下面的點上限制該流,那麼,我們必須採取某種策略,使得該流從s出發後不會走到限制範圍外的點,方法就是處理出所有受限制的點,直接連邊,並且,這些流只能到達匯點

一組不這麼做會錯的數據

5 1
0YZ52
3Y481
66Y68
Y1665
35923

9YZ89
2Y876
08Y19
Y1891
24689

答案是88,不這麼拆點答案就是89,在這裏wa了很久

另外,這道題還要預先處理出爆炸點到每個實驗室的最短路,以及每個有科學家的實驗室到所有具有救生艙的實驗室的最短路,如果實驗室a到實驗室b的最短路徑小於等於爆炸點到實驗室b的最短路徑,就可以連邊a->b'

由於邊權爲1,可以用bfs實現


代碼:

#include<iostream>
#include<memory.h>
#include<string>
#include<cstdio>
#include<algorithm>
#include<math.h>
#include<stack>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int MAX=10005;
const int inf=1<<30;
struct node 
{
	int u,v,c,next;
}g[MAX*10];
struct Node 
{
	int x,y,step;
};
int adj[MAX],dis[MAX],cur[MAX],pre[MAX],num[MAX],n,e,s,t,vn,T;
int sx,sy,dir[4][2]={1,0,-1,0,0,1,0,-1};
int flag[15][15],vis[15][15];
char mat1[15][15],mat2[15][15];
bool in(int x,int y)
{
	if(x<1||x>n||y<1||y>n)
		return false;
	return true;
}
void add(int u,int v,int c)  
{  
     g[e].u=u; g[e].v=v; g[e].c=c; g[e].next=adj[u]; adj[u]=e++;  
     g[e].u=v; g[e].v=u; g[e].c=0; g[e].next=adj[v]; adj[v]=e++; 
     //if(u==s||v==t)
     //if(u==12+n*n&&v==17)
	 //cout<<u<<" "<<v<<" "<<c<<endl; 
}  
void bfs1()
{
	queue<Node>que;
	Node now,next;
	now.x=sx; now.y=sy; now.step=0;
	que.push(now);
	memset(flag,0x7f,sizeof(flag));
	memset(vis,0,sizeof(vis));
	vis[now.x][now.y]=1;
	while(!que.empty())
	{
		now=que.front();
		que.pop();
		flag[now.x][now.y]=now.step;
		if(now.step>T)
			break;
		for(int i=0;i<4;i++)
		{
			int xx=now.x+dir[i][0];
			int yy=now.y+dir[i][1];
			if(in(xx,yy)&&mat1[xx][yy]!='Y'&&!vis[xx][yy])
			{
				next.x=xx; next.y=yy; next.step=now.step+1;
				vis[xx][yy]=1;
				que.push(next);
			}
		}
	}
}
void bfs2(int i,int j)
{
	queue<Node>que;
	Node now,next;
	now.x=i; now.y=j; now.step=0;
	que.push(now);
	memset(vis,0,sizeof(vis));
	vis[now.x][now.y]=1;
	while(!que.empty())
	{
		now=que.front();
		que.pop();
		if(now.step>T)
			break;
		if(flag[now.x][now.y]<now.step)
			continue;
		if(flag[now.x][now.y]==now.step&&(mat2[now.x][now.y]<'1'||mat2[now.x][now.y]>'9'))
			continue;
		if(mat2[now.x][now.y]>='1'&&mat2[now.x][now.y]<='9')
		{
			if(now.x!=i||now.y!=j)
			add((i-1)*n+j,(now.x-1)*n+now.y+n*n,inf);
			if(flag[now.x][now.y]==now.step)
				continue;
		}
		for(int i=0;i<4;i++)
		{
			int xx=now.x+dir[i][0];
			int yy=now.y+dir[i][1];
			if(in(xx,yy)&&mat1[xx][yy]!='Y'&&!vis[xx][yy])
			{
				next.x=xx; next.y=yy; next.step=now.step+1;
				vis[xx][yy]=1;
				que.push(next);
			}
		}
	}
}
int sap()    
{    
    int i,u,v,flag,aug=inf,flow=0;    
    for(i=0;i<=vn;i++)    
    {    
        cur[i]=adj[i];    
        num[i]=dis[i]=0;    
    }    
    num[0]=vn;    
    pre[s]=u=s;    
    while(dis[s]<vn)    
    {    
        flag=0;    
        for(i=cur[u];i!=-1;i=g[i].next)    
        {    
            v=g[i].v;    
            if(g[i].c&&dis[u]==dis[v]+1)    
            {    
                flag=1;    
                aug=min(aug,g[i].c);    
                pre[v]=u;    
                cur[u]=i;    
                u=v;    
                if(u==t)    
                {    
                    flow+=aug;    
                    while(u!=s)    
                    {    
                        u=pre[u];    
                        g[cur[u]].c-=aug;    
                        g[cur[u]^1].c+=aug;    
                    }    
                    aug=inf;    
                }    
                break;    
            }    
        }    
        if(flag)    
            continue;    
        if(--num[dis[u]]==0)    
            break;    
        for(dis[u]=vn,i=adj[u];i!=-1;i=g[i].next)    
        {    
            v=g[i].v;    
            if(g[i].c&&dis[v]<dis[u])    
            {    
                dis[u]=dis[v];    
                cur[u]=i;    
            }    
        }    
        dis[u]++;    
        num[dis[u]]++;    
        u=pre[u];    
    }    
    return flow;    
}   
int main()
{
	int i,j,k;
	while(scanf("%d%d",&n,&T)!=EOF)
	{
		memset(adj,-1,sizeof(adj));
		e=0;
		s=0;
		t=n*n+n*n+1;
		vn=t+1;
		for(i=1;i<=n;i++)
		{
			scanf("%s",mat1[i]+1);
			for(j=1;j<=n;j++)
			{
				if(mat1[i][j]>='1'&&mat1[i][j]<='9')
				{
					add(s,(i-1)*n+j,mat1[i][j]-'0');
				}
				if(mat1[i][j]=='Z')
				{
					sx=i;
					sy=j;
				}
			}
		}
		for(i=1;i<=n;i++)
		{
			scanf("%s",mat2[i]+1);
			for(j=1;j<=n;j++)
			{
				add((i-1)*n+j,(i-1)*n+j+n*n,inf);
				if(mat2[i][j]>='1'&&mat2[i][j]<='9')
					add((i-1)*n+j+n*n,t,mat2[i][j]-'0');
			}
		}
		bfs1();
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=n;j++)
			{
				if(mat1[i][j]>='1'&&mat1[i][j]<='9')
					bfs2(i,j);
			}
		}		
		i=1;
		printf("%d\n",sap());
		/*for(i=1;i<=100;i++)
		{
			for(j=adj[i];j!=-1;j=g[j].next)
			{
				if(g[j].v==t)
					printf("%d %d\n",i,g[j^1].c);
			}
		} */
		/*for(i=1;i<e;i+=2)
		{
			if(g[i].u==g[i].v+n*n)
				continue;
			printf("%d %d %d\n",g[i].v>n*n?g[i].v-n*n:g[i].v,g[i].u>n*n?g[i].u-n*n:g[i].u,g[i].c);
		} */
	}
	return 0;
}


發佈了242 篇原創文章 · 獲贊 5 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章