洛谷P2770:航空路线问题【最大费用最大流】

题目描述

      给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。

(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市)。

(2)除起点城市外,任何城市只能访问 1 次。

      对于给定的航空图,试设计一个算法找出一条满足要求的最佳航空旅行路线.

题解

      这道题目按我的理解就是求一个包含头结点和尾节点的一个最大环。

      所以我们可以把这个环拆成两条从头结点到尾节点的路径,那么使这两条路径长度相加-2最长即可。

      我们来拆点,把i城市拆成入点u_i,出点v_i。那么x->y有一条边,便从v_y向u_x连一条流量为INF,费用为0的边,因为走边不用消耗费用。

      既然要求最长,那么我们就要从原来的最小费用最大流,改为最大费用最大流。

      有人肯定想问,那在SPFA求最长路的时候应该怎么做,很简单,我们把边权改负就行了。

      每个点的入点u_i到每个点的出点v_i建一条流量为1,费用为-1的边,表示飞机只能在这个城市中转一次(只能经过这个城市一次),费用总数的绝对值便是经过城市总数,不要忘记减2。因为头结点和尾节点都是经过两次的。

      但是1和n的这样的边要建两条,因为这样才能把流量分出去。

      begin源点到u_1建一条流量为2,费用为0的边,表示要找到两条从起点到终点的路径。

      v_n到end汇点建一条流量为2,费用为0的边,同理。

下列情况要特判:

1.只经过最东端城市和最西端城市,不用减2.

2.在dfs输出答案时,记得掌握好这条边是否走过的判断依据。

代码有点丑,主要还是掌握思路哈

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 1e9
using namespace std;

int n,m;
struct edge{int x,y,next,c,cos,f;};
edge s[10010];
map pei;
int first[210];
int ip[210];
int len=1;
int begin,end;
int h[210],min_flow[210];
queue f;
int answer[2][210];
int tan=0,tans=0;
string fact[110];
bool tf[210];
int last=0;

int mmin(int x,int y)
{
	return xh[x]+s[i].cos && s[i].c>0)
			{
				h[y]=h[x]+s[i].cos;
				ip[y]=i;
				min_flow[y]=mmin(min_flow[x],s[i].c);
				if(!tf[y])
				{
					tf[y]=true;
					f.push(y);
				}
			}
		}
	}
	if(h[end]==1061109567) return 0;
	flow+=min_flow[end];
	cost+=-h[end]*min_flow[end];
	int now=end;
	while(now!=begin)
	{
		int i=ip[now];
		s[i].c-=min_flow[end];
		s[i^1].c+=min_flow[end];
		now=s[i].x;
	}
	return 1;
}

int cost_flow()
{
	int cost=0,flow=0;
	while(SPFA(cost,flow));
	if(s[len].c<2) return 0;
	return cost==2?cost:cost-2;
}

void dfs_1(int x)
{
	for(int i=first[x];i!=0;i=s[i].next)
	{
		if(s[i].c!=s[i].f && s[i].f>0) 
		{
			if(s[i].y<=n && s[i].y>=1)
				cout<0)
		{
			if(s[i].y<=n && s[i].y>=1)
				cout<>fact[i];
		pei[fact[i]]=i;
		ins(i,n+i,1,-1);
	}
	for(int i=1;i<=m;i++)
	{
		string x,y;
		cin>>x>>y;
		ins(n+pei[x],pei[y],INF,0);
	}
	ins(1,n+1,1,-1);
	ins(n,n+n,1,-1);
	ins(begin,1,2,0);
	ins(2*n,end,2,0);
	int p=cost_flow();
	if(p==0) printf("No Solution!");
	else
	{
		printf("%d\n",p);
		int x=1;
		cout<










你可能感兴趣的:(洛谷P2770:航空路线问题【最大费用最大流】)