社区讨论

只用最大流行吗?

P2770航空路线问题参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mi6n5asm
此快照首次捕获于
2025/11/20 07:36
4 个月前
此快照最后确认于
2025/11/20 07:36
4 个月前
查看原帖
有人帮我瞧瞧吗?只用的最大流,遍历残量为0的边计数。
只得27分
CPP
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
const int maxn=10000+10;
const int inf=1e9;
struct point
{
    int to;
    int nxt;
    int cap;
    int ff;
}edge[maxn];
int n,m,tot;
map<string,int> la;
int head[maxn],level[maxn];
int to1[maxn],to2[maxn],vis[maxn],ans[maxn];
string id[maxn];
int S,T,anum;
inline void add(int u,int v,int c)
{
    edge[tot].to=v;
    edge[tot].nxt=head[u];
    edge[tot].cap=c;
    head[u]=tot;
    edge[tot].ff=1;
    tot++;
    edge[tot].to=u;
    edge[tot].nxt=head[v];
    edge[tot].cap=0;
    head[v]=tot;
    edge[tot].ff=0;
    tot++;    
}
inline bool Bfs()
{
    queue<int> q;
    memset(level,-1,sizeof(level));
    level[S]=1;
    q.push(S);
    while(!q.empty())
    {
        int tt=q.front();
        q.pop();
        for(int i=head[tt];~i;i=edge[i].nxt)
        if(level[edge[i].to]==-1 && edge[i].cap>0)
        { 
            level[edge[i].to]=level[tt]+1;
            q.push(edge[i].to);
        }
    }
    if(level[T]==-1)
        return false;
    return true;
}
int dfs(int x,int low)
{
    if(x==T || low==0)
        return low;
    int res=0;
    for(int i=head[x];~i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(level[v]==level[x]+1 && edge[i].cap)    
        {
            int ww=dfs(v,min(edge[i].cap,low));
            res+=ww;
            low-=ww;
            edge[i].cap-=ww;
            edge[i^1].cap+=ww;
            if(low==0)
                break;
        }
    }    
    return res;
}
inline int Dinic()
{
    int res=0;
    while(Bfs())
    {
        res+=dfs(S,inf);    
    }
    return res;
}
inline void Output()
{
    int tmp=1+n,cnt=0;
    vis[1]=1;
    while(tmp!=n+n)
    {
        for(int i=head[tmp];~i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(edge[i].ff && !vis[v] && edge[i].cap==0)
            {
                vis[v]=1;
                to1[tmp-n]=v;
                tmp=v+n;
                break;    
            }    
        }
    }
    tmp=1+n;
    vis[n]=0;
    memset(to2,0,sizeof(to2));
    while(tmp!=n+n)
    {
        for(int i=head[tmp];~i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(edge[i].ff && !vis[v] && edge[i].cap==0)
            {
                vis[v]=1;
                to2[v]=tmp-n;
                tmp=v+n;
                break;    
            }    
        }
    }
    for(int i=1;i<=n;i++)
        if(vis[i])
            cnt++;
    cout<<cnt<<endl;
    tmp=1;
    while(to1[tmp]!=0)
    {
        cout<<id[tmp]<<endl;
        tmp=to1[tmp];    
    }
    cout<<id[tmp]<<endl;
    tmp=to2[n];
    while(to2[tmp]!=0)
    {
        cout<<id[tmp]<<endl;
        tmp=to2[tmp];    
    }
    cout<<id[1]<<endl;    
}
/*void out(int x)
{
    ans[++anum]=x;
    for(int i=fst[x];i!=-1;i=nxt[i])
        if(e[i].c==0&&e[i].w>=0)
        {
            out(e[i].v);
            e[i].c=1;
            return;
        }
}*/
int main()
{
    scanf("%d%d",&n,&m);
    string ss;
    S=1,T=2*n;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++)
    {
        cin>>ss;
        la[ss]=i;
        id[i]=ss;    
    }
    for(int i=2;i<n;i++)
        add(i,i+n,1);
    add(1,1+n,2);
    add(n,n+n,2);
    for(int i=1;i<=m;i++)
    {
        string s1,s2;
        cin>>s1>>s2;
        if(la[s1]>la[s2])
            swap(s1,s2);
        add(la[s1]+n,la[s2],1);
    }
    int Maxflow=Dinic();
    if(Maxflow==0)
    {
        printf("No Solution!");
        return 0;    
    }
    else if(Maxflow==1)
    {
        cout<<2<<endl<<id[1]<<endl<<id[n]<<endl<<id[1];
        return 0;    
    }
    Output();
/*    if(Maxflow==0){printf("No Solution!\n");return 0;}
    else if(Maxflow==1)
    {cout<<2<<endl<<id[1]<<endl<<id[n]<<endl<<id[1]<<endl;return 0;}
    else//否则两条合法航线
    {
        printf("%d\n",cost/2-1);
        out(S);//寻找经过的点
        for(int i=1;i<=anum;i++)if(ans[i]<=n)cout<<id[ans[i]]<<endl;
        anum=0;
        out(S);
        for(int i=anum-2;i>=1;i--)if(ans[i]<=n)cout<<id[ans[i]]<<endl;
    }*/    
    return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...