zoukankan      html  css  js  c++  java
  • P2770 航空路线问题

    (color{#0066ff}{题目描述})

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

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

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

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

    (color{#0066ff}{输入格式})

    第 1 行有 2 个正整数 N 和 V,N 表示城市数,N<100,V 表示直飞航线数。

    接下来的 N 行中每一行是一个城市名,可乘飞机访问这些城市。城市名出现的顺序是从西向东。也就是说,设 i,j 是城市表列中城市出现的顺序,当 i>j 时,表示城市 i 在城市 j 的东边,而且不会有 2 个城市在同一条经线上。城市名是一个长度不超过15 的字符串,串中的字符可以是字母或阿拉伯数字。例如,AGR34 或 BEL4。

    再接下来的 V 行中,每行有 2 个城市名,中间用空格隔开,如 city1 city2 表示 city1到 city2 有一条直通航线,从 city2 到 city1 也有一条直通航线。

    (color{#0066ff}{输出格式})

    文件第 1 行是旅行路线中所访问的城市总数 M。 接下来的 M+1 行是旅行路线的城市名,每行写 1 个城市名。首先是出发城市名,然后按访问顺序列出其它城市名。 注意,最后 1 行(终点城市)的城市名必然是出发城市名。如果问题无解,则输出“No Solution!”。

    (color{#0066ff}{输入样例})

    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
    

    (color{#0066ff}{输出样例})

    7
    Vancouver
    Edmonton
    Montreal
    Halifax
    Toronto
    Winnipeg
    Calgary
    Vancouver 
    

    (color{#0066ff}{数据范围与提示})

    有spj

    (color{#0066ff}{题解})

    题意就是求两条不相交的从1-n的路径,使得经过的点尽可能多

    所以,若本图合法,则跑完最大流一定(leq 2)

    跑完就知道走了哪些点

    因为要使路径最长

    所以跑费用流,对边赋权为1跑最长路

    每个点要拆点,拆成的两个点连权为1的边

    s,t作为起点终点,再练一条权为0的边

    对于图中所给边,直接连权为0的边就行

    最后重新建图,dfs

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<string>
    #define _ 0
    #define LL long long
    inline LL in()
    {
    	LL x=0,f=1; char ch;
    	while(!isdigit(ch=getchar()))(ch=='-')&&(f=-f);
    	while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
    	return x*f;
    }
    const int inf=0x7fffffff;
    int n,v,s,t,cnt=1;
    std::queue<int> q;
    struct node
    {
    	int to,dis,nxt,can;
    	node(int to=0,int dis=0,int nxt=0,int can=0):to(to),dis(dis),nxt(nxt),can(can){}
    }e[1050500];
    int dis[1200],change[1200],head[1200],road[1200];
    bool vis[1200],flag;
    std::map<std::string,int> mp;
    std::string f[1200],ss1,ss2;
    int aa[1200],bb[1200];
    int h[1200],st[1200],top;
    inline void add(int from,int to,int dis,int can)
    {
    	e[++cnt]=node(to,dis,head[from],can);
    	head[from]=cnt;
    }
    inline void link(int from,int to,int dis,int can)
    {
    	add(from,to,dis,can);
    	add(to,from,-dis,0);
    }
    inline bool spfa()
    {
    	for(int i=1;i<=n<<1;i++) dis[i]=-inf,change[i]=inf;
    	dis[s]=0;
    	q.push(s);
    	while(!q.empty())
    	{
    		int tp=q.front(); q.pop();
    		vis[tp]=false;
    		for(int i=head[tp];i;i=e[i].nxt)
    		{
    			int go=e[i].to;
    			if(dis[go]<dis[tp]+e[i].dis&&e[i].can>0)
    			{
    				dis[go]=dis[tp]+e[i].dis;
    				change[go]=std::min(change[tp],e[i].can);
    				road[go]=i;
    				if(!vis[go]) vis[go]=true,q.push(go);
    			}
    		}
    	}
    	return change[t]!=inf;
    }
    inline void add(int from,int to)
    {
    	e[++cnt]=node(to,0,h[from],0);
    	h[from]=cnt;
    }
    inline void dfs(int x)
    {
    	st[++top]=x;
    	vis[x]=1;
    	for(int i=h[x];i;i=e[i].nxt)
    	{
    		int go=e[i].to;
    		if(!vis[go]) dfs(go);
    	}
    }
    inline void mcmf()
    {
    	int flow=0;
    	int cost=0;
    	while(spfa())
    	{
    		flow+=change[t];
    		cost+=change[t]*dis[t];
    		for(int i=t;i!=s;i=e[road[i]^1].to)
    		{
    			e[road[i]].can-=change[t];
    			e[road[i]^1].can+=change[t];
    		}
    	}
    	if(cost==2)
    	{
    		printf("2
    ");
    		std::cout<<f[1]<<'
    '<<f[n]<<'
    '<<f[1];
    	}
    	else if(flow==2)
    	{
    		printf("%d
    ",cost);
    		for(int i=1;i<=v;i++)
                for(int j=head[aa[i]+n];j;j=e[j].nxt)
                    if(e[j].to==bb[i]&&!e[j].can)
                        add(aa[i],bb[i]),add(bb[i],aa[i]);
    		dfs(s);
    		for(int i=1;i<=top;i++) std::cout<<f[st[i]]<<'
    ';
    		std::cout<<f[1];
    	}
    	else return (void)(printf("No Solution!"));	
    }
    int main()
    {
    	n=in(),v=in();
    	s=1,t=n*2;
    	for(int i=1;i<=n;i++)
    	{
    		std::cin>>f[i];
    		mp[f[i]]=i;
    		link(i,i+n,1,1);
    	}
    	link(s,s+n,0,1);
    	link(n,n+n,0,1);
    	for(int i=1;i<=v;i++)
    	{	
    		std::cin>>ss1>>ss2;
    		if(mp[ss1]>mp[ss2]) std::swap(ss1,ss2);
    		aa[i]=mp[ss1],bb[i]=mp[ss2];
    		link(mp[ss1]+n,mp[ss2],0,1);
    	}
    	mcmf();
    	return 0;
    }
    
  • 相关阅读:
    uni-app添加阿里巴巴图标库图标
    uni-app创建list列表
    vue-cli3.0运行单独的vue文件
    vue-cli3.0创建项目
    vue使用splice操作数组更新页面
    关于undefined出现的原因
    redux devtools的使用
    placeholder的颜色
    PHP json_encode 中文乱码
    浅谈服务治理与微服务
  • 原文地址:https://www.cnblogs.com/olinr/p/10105179.html
Copyright © 2011-2022 走看看