zoukankan      html  css  js  c++  java
  • 洛谷 P3356 火星探险问题 【最大费用最大流】

    输出方案好麻烦啊
    拆点,石头的连(i,i',1,1)(i,i',inf,0)表示可以取一次价值1,空地直接连(i,i',inf,0),对于能走到的两个格子(不包括障碍),连接(i',j,inf,0),然后连接s和起点,终点和t,流量为探测车的数量。然后跑最大费用最大流。
    关于输出方案,dfs即可,每经过一次就把反向边的流量减一即可,注意不要输出i'

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=1000005,inf=1e9;
    int q,n,m,a[40][40],bs,h[N],cnt=1,dis[N],fr[N],s,t,ans,sum;
    bool v[N];
    struct qwe
    {
    	int ne,no,to,va,c;
    }e[N<<2];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void add(int u,int v,int w,int c)
    {
    	cnt++;
    	e[cnt].ne=h[u];
    	e[cnt].no=u;
    	e[cnt].to=v;
    	e[cnt].va=w;
    	e[cnt].c=c;
    	h[u]=cnt;
    }
    void ins(int u,int v,int w,int c)
    {
    	add(u,v,w,c);
    	add(v,u,0,-c);
    }
    bool spfa()
    {
    	queue<int>q;
    	for(int i=s;i<=t;i++)
    		dis[i]=-inf;
    	dis[s]=0;
    	v[s]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		v[u]=0;
    		for(int i=h[u];i;i=e[i].ne)
    			if(e[i].va>0&&dis[e[i].to]<dis[u]+e[i].c)
    			{
    				dis[e[i].to]=dis[u]+e[i].c;
    				fr[e[i].to]=i;
    				if(!v[e[i].to])
    				{
    					v[e[i].to]=1;
    					q.push(e[i].to);
    				}
    			}
    	}
    	return dis[t]!=-inf;
    }
    void mcf()
    {
    	int x=inf;
    	for(int i=fr[t];i;i=fr[e[i].no])
    		x=min(x,e[i].va);
    	for(int i=fr[t];i;i=fr[e[i].no])
    	{
    		e[i].va-=x;
    		e[i^1].va+=x;
    		ans+=e[i].c*x;
    	}
    	sum+=x;
    }
    void dfs(int x,int y,int u,int k)
    {
    	int kx,ky,mv;
    	for(int i=h[u];i;i=e[i].ne)
    		if(e[i].to!=s&&e[i].to!=t&&e[i].to!=u-bs&&e[i^1].va>0)
    		{
    			e[i^1].va--;
    			if(e[i].to>bs)
    			{
    				dfs(x,y,e[i].to,k);
    				return;
    			}
    			if(e[i].to==(x-1)*n+y+1)
    				kx=x,ky=y+1,mv=1;
    			else
    				kx=x+1,ky=y,mv=0;
    			printf("%d% d
    ",k,mv);
    			dfs(kx,ky,e[i].to+bs,k);
    			return;
    		}
    }
    int main()
    {
    	q=read(),n=read(),m=read();
    	bs=n*m,s=0,t=n*m+bs+1;
    	for(int i=1;i<=m;i++)
    		for(int j=1;j<=n;j++)
    			a[i][j]=read();
    	for(int i=1;i<=m;i++)
    		for(int j=1;j<=n;j++)
    			if(a[i][j]!=1)
    			{
    				int id=(i-1)*n+j;
    				if(a[i][j]==2)
    					ins(id,id+bs,1,1);
    				ins(id,id+bs,inf,0);
    				if(i!=m&&a[i+1][j]!=1)
    					ins(id+bs,id+n,inf,0);
    				if(j!=n&&a[i][j+1]!=1)
    					ins(id+bs,id+1,inf,0);
    			}
    	if(a[1][1]!=1)
    		ins(s,1,q,0);
    	if(a[m][n]!=1)
    		ins(n*m+bs,t,q,0);
    	while(spfa())
    		mcf();
    	for(int i=1;i<=sum;i++)
    		dfs(1,1,1,i);
    	return 0;
    }
    
  • 相关阅读:
    java_oop_方法2
    POJ 3276 Face The Right Way(反转)
    POJ 3276 Face The Right Way(反转)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 2566 Bound Found(尺取法,前缀和)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3320 Jessica's Reading Problem(尺取法)
    POJ 3061 Subsequence(尺取法)
    POJ 3061 Subsequence(尺取法)
    HDU 1222 Wolf and Rabbit(欧几里得)
  • 原文地址:https://www.cnblogs.com/lokiii/p/8431575.html
Copyright © 2011-2022 走看看