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

记得cnt=1!!因为是无向图所以可以把回来的路看成另一条向东的路。字符串用map处理即可。拆点限制流量,除了1和n是(i,i+n,2)表示可以经过两次,其他点都拆成(i,i+n,1),费用设为1,原图中的边(i,j)连接(i+n,j,1),注意特判掉i==q&&j==nst直接相连的情况,流量要设为2,然后跑最大费用最大流,如果流量小于2就是无解,否则分别从s和tdfs输出方案。

记得输出方案前先输出一次起点。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<string>
using namespace std;
const int N=1000005,inf=1e9;
int n,m,s,t,h[N],cnt=1,dis[N],fr[N],a[N][2],ans,sum;
bool v[N];
string c1,c2,ha[N];
map<string,int>mp;
struct qwe
{
    int ne,no,to,va,c;
}e[N<<2];
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)
{//cout<<u<<" "<<v<<" "<<w<<endl;
    add(u,v,w,c);
    add(v,u,0,-c);
}
bool spfa()
{
    for(int i=s;i<=t;i++)
        dis[i]=-inf;
    queue<int>q;
    q.push(s);
    dis[s]=0;
    v[s]=1;
    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&&dis[e[i].to]<dis[u]+e[i].c)
            {
                fr[e[i].to]=i;
                dis[e[i].to]=dis[u]+e[i].c;
                if(!v[e[i].to])
                {
                    v[e[i].to]=1;
                    q.push(e[i].to);
                }
            }
    }//cout<<dis[t]<<endl;
    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);
    sum+=x;
    for(int i=fr[t];i;i=fr[e[i].no])
    {
        e[i].va-=x;
        e[i^1].va+=x;
        ans+=x*e[i].c;//cout<<e[i].c<<endl;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    s=1,t=n+n;
    for(int i=1;i<=n;i++)
    {
        cin>>c1;
        mp[c1]=i;
        ha[i]=c1;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>c1>>c2;//cout<<c1<<endl<<c2<<endl;
        int x=mp[c1],y=mp[c2];//cout<<x<<" "<<y<<endl;
        if(x>y)
            swap(x,y);
        if(x==1&&y==n)
            ins(x+n,y,2,0);
        else
            ins(x+n,y,1,0);
    }
    ins(1,1+n,2,1);
    ins(n,n+n,2,1);
    for(int i=2;i<n;i++)
        ins(i,i+n,1,1);
    while(spfa())
        mcf();//cout<<sum<<" "<<ans<<endl;
    if(sum<2)
    {
        puts("No Solution!");
        return 0;
    }
    cout<<ans-2<<endl;
    cout<<ha[1]<<endl;
    for(int i=h[s+n],j,k;i;i=e[i].ne)
        if(!e[i].va&&!(i&1))
        {
            k=e[i].to;
            while(k)
            {
                cout<<ha[k]<<endl;
                v[k]=1;
                for(j=h[k+n],k=0;j;j=e[j].ne)
                    if(!e[j].va&&!(j&1))
                    {
                        k=e[j].to;
                        break;
                    }
            }
            break;
        }
    for(int i=h[t-n],j,k;i;i=e[i].ne)
        if(!e[i^1].va&&(i&1)&&!v[e[i].to-n])
        {
            k=e[i].to-n;
            while(k)
            {
                cout<<ha[k]<<endl;
                v[k]=1;
                for(j=h[k],k=0;j;j=e[j].ne)
                    if(!e[j^1].va&&(j&1))
                    {
                        k=e[j].to-n;
                        break;
                    }
            }
            break;
        }
    return 0;
}

原文地址:https://www.cnblogs.com/lokiii/p/8428547.html

时间: 2024-10-24 04:43:41

洛谷 P2770 航空路线问题【最大费用最大流】的相关文章

[洛谷3381]【模板】最小费用最大流

思路:最小费用最大流模板题.用EdmondsKarp,增广时使用SPFA求最短路. 1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 inline int getint() { 6 char ch; 7 while(!isdigit(ch=getchar())); 8 int x=ch^'0'; 9 while(isdigit(ch=getchar())

洛谷 P3381 【模板】最小费用最大流

题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用. 输入输出样例 输入样例#

[洛谷P3381]【模板】最小费用最大流

题目大意:给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 解题思路:最小费用最大流模板.虽说此题最后两个点的时限是1200ms,但我觉得耗时在1000ms以上很不爽,于是对代码进行全面优化.然而最后一个点仍然有1050+ms.最后逼我开大招(代码第一行),瞬间只有不到900ms,大爽. C++ Code: %:pragma GCC optimize("Ofast") #include<cstdio> #in

洛谷 3381 【模板】最小费用最大流

https://www.luogu.org/problem/show?pid=3381 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一

洛谷P4016 负载平衡问题(最小费用最大流)

题目描述 GG 公司有 nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入输出格式 输入格式: 文件的第 11 行中有 11 个正整数 nn ,表示有 nn 个仓库. 第 22 行中有 nn 个正整数,表示 nn 个仓库的库存量. 输出格式: 输出最少搬运量. 输入输出样例 输入样例#1: 复制 5 17 9 14 16 4 输出样例#1: 复制 11 说明 1 \leq n \leq

洛谷 P4012 深海机器人问题【费用流】

题目链接:https://www.luogu.org/problemnew/show/P4012 洛谷 P4012 深海机器人问题 输入输出样例 输入样例#1: 1 1 2 2 1 2 3 4 5 6 7 2 8 10 9 3 2 0 0 2 2 2 输出样例#1: 42 说明 题解:建图方法如下: 对于矩阵中的每个点,向东.向北分别与其相邻点都要连两条边(重边): 1)容量为1,费用为该边价值的边: 2)容量为INF,费用为0的边(因为多个深海机器人可以在同一时间占据同一位置). 对于每个起点

P2770 航空路线问题

\(\color{#0066ff}{题目描述}\) 给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线.现要求找出一条满足下述限制条件的且途经城市最多的旅行路线. (1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市). (2)除起点城市外,任何城市只能访问 1 次. 对于给定的航空图,试设计一个算法找出一条满足要求的最佳航空旅行路线. \(\color{#0066ff}{输入格式}\) 第 1 行有 2 个正整数 N 和 V,N

[洛谷1649]障碍路线&lt;BFS&gt;

题目链接:https://www.luogu.org/problem/show?pid=1649 历经千辛万苦,我总算是把这个水题AC了,现在心里总觉得一万只草泥马在奔腾: 这是一道很明显的BFS,然后我也明显的看出来了 但是,我就是WA了很久很久,在调试第一个晚上后,我发现读入是存在空格的,而不是数据问题 然后第二个问题就是,BFS找到的第一个终点不一定就是最优的答案(当然第二个问题是我重新打了一次猛然发现之前没注意的一点) 注意到这两点,其实这道题就没难度了 然后这道题的处理需要注意一个地方

洛谷 P3376 【【模板】网络最大流】

题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含三个正整数ui.vi.wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi) 输出 一行,包含一个正整数,即为该网络的最大流. 样例输入 4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40 样例输出 50 数据规模: 对于30%的数据:N<=10,M<=2