LUOGU 2770 air route network flow problems 24 questions

Copyright: https: //blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/90813425

title

LUOGU 2770
Title Description

Given an aerial map, vertices in the graph representing the urban edges represent direct access route between the two cities. It is required to find a maximum of the following restrictions and travel route passing through the city meet.
(1) from the westernmost city of departure, one way to reach the most eastern end of the city from west to east via a number of cities, and then fly back to the starting point of a one-way (available via a number of cities) from east to west.
(2) In addition to the starting point of the city, any city can only visit once.
For a given aeronautical charts, Try to design an algorithm to find the best air travel a route to meet the requirements.

Input and output format
input format:

Line 1 has two positive integers N and V, N represents the number of cities, N <100, V represents the number of direct routes.
The next N lines each row is a city name, you can access the city by plane. City name appears in order from west to east. That is, set i, j is the order listed in urban cities occurs when i> j, the urban city i j represents the east, and will not have two cities in the same meridian. City name is a string of no longer than 15 characters in the string can be letters or digits. For example, AGR34 or BEL4.
The next V-lines, each row has two city names, separated by a space intermediate, as represented city1 city1 city2 city2 to have a straight route from city2 city1 to have a straight course.

Output formats:

Line 1 is the total number of pieces of city itineraries visit M. The next line is the M + 1 itinerary city name per line to write a city name. The first is the departure city name, then press the access order lists the name of the other cities. Note that the last line (the end of the city) the city name must be the name of the departure city. If the problem is no solution, output "No Solution!".

Input Output Sample
Input Sample # 1:

8 9
Vancouver
Yellowknife
Edmonton
Calgary
Winnipeg
Toronto
Montreal
Halifax
Vancouver Edmonton
Vancouver Calgary
Calgary Winnipeg
Winnipeg Toronto
Toronto Halifax
Montreal Halifax
Edmonton Montreal
Edmonton Yellowknife
Edmonton Calgary

Output Sample # 1:

7
Vancouver
Edmonton
Montreal
Halifax
Toronto
Winnipeg
Calgary
Vancouver

Explanation

Thank @FlierKing provide spj

analysis

Meaning of the questions is probably seek from 1 1 to n n paths, will not be repeated up through the number of edges. .

Routine: each point split into two, A i , B i A_i,B_i ,then A i A_i To B i B_i Even capacity 1 1 at a cost of 1 1 side, to ensure that each point is selected only once. .

then 1 1 and n n is special, for the capacity to 2 2 , and then a linked side, B i B_i to A j A_j Even side, capacity 1 1 , the cost of 1 1 。。

To pick up points, then the cost is to the maximum, so run a maximum cost flow, relatively sb, even forgot to change the board, but also even the shortest run took 27 minutes?

Find solutions, then direct d f s dfs , and with the positive output can be backwards. .

Feelings is the string input and output Gaosi really fast to me, the whole problem because the string out for an afternoon. .

There are several places in the code of note, see the references it. .

Reference: bztMinamoto .

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=5010,maxm=5e5+10,inf=0xcfcfcfcf;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}

template<typename T>inline void write(T x)
{
	if (!x) { putchar('0'); return ; }
	if (x<0) putchar('-'),x=-x;
	T num=0,ch[20];
	while (x) ch[++num]=x%10+48,x/=10;
	while (num) putchar(ch[num--]);
}

int ver[maxm],edge[maxm],Next[maxm],cost[maxm],head[maxn],len=1;
inline void add(int x,int y,int z,int c)
{
	ver[++len]=y,edge[len]=z,cost[len]=c,Next[len]=head[x],head[x]=len;
	ver[++len]=x,edge[len]=0,cost[len]=-c,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxn],incf[maxn],pre[maxn];
bool vis[maxn];
inline bool spfa()
{
	memset(dist,0xcf,sizeof(dist));
	memset(vis,0,sizeof(vis));
	queue<int>q;q.push(s);
	dist[s]=0,vis[s]=1,incf[s]=1<<30;
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		vis[x]=0;
		for (int i=head[x]; i; i=Next[i])
		{
			if (!edge[i]) continue;
			int y=ver[i];
			if (dist[y]<dist[x]+cost[i])
			{
				dist[y]=dist[x]+cost[i];
				incf[y]=min(incf[x],edge[i]);
				pre[y]=i;
				if (!vis[y]) q.push(y),vis[y]=1;
			}
		}
	}
	if (dist[t]==inf) return false;
	else return true;
}

int maxflow,ans;
inline void update()
{
	int x=t;
	while (x!=s)
	{
		int i=pre[x];
		edge[i]-=incf[t];
		edge[i^1]+=incf[t];
		x=ver[i^1];
	}
	maxflow+=incf[t];
	ans+=dist[t]*incf[t];
}

int id[maxn],cnt;
inline void dfs(int x)
{
	id[++cnt]=x;
	for (int i=head[x]; i; i=Next[i])
	{
		int y=ver[i];
		if (!edge[i] && cost[i]>=0)
		{
			dfs(y);
			edge[i]=1;
			return ;
		}
	}
}

map<string,int>Map;
string name[maxn];
int main()
{
	int n,v;
	read(n);read(v);
	s=1,t=n<<1;

	string s1,s2;
	for (int i=1; i<=n; ++i)
	{
		cin>>s1;
		Map[s1]=i;
		name[i]=s1;
		add(i,i+n,1,1);
	}

	bool f=0;
	for (int i=1; i<=v; ++i)
	{
		cin>>s1>>s2;
		int a=Map[s1],b=Map[s2];
		if (a>b) swap(a,b);
		if (a==1 && b==n) f=1;
		add(a+n,b,1,1);
	}
	add(1,1+n,1,1);
	add(n,n+n,1,1);

	while (spfa()) update();
	if (!maxflow || (maxflow==1 && !f)) return puts("No Solution!"),0;
	if (maxflow==1 && f) return puts("2"),cout<<name[1]<<endl<<name[n]<<endl<<name[1]<<endl,0;

	write((ans>>1)-1),puts("");
	dfs(s);
	for (int i=1; i<=cnt; ++i)
		if (id[i]<=n) cout<<name[id[i]]<<endl;

	cnt=0;
	dfs(s);
	for (int i=cnt-2; i; --i)
		if (id[i]<=n) cout<<name[id[i]]<<endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/huashuimu2003/article/details/90813425
Recommended