社区讨论
只用最大流行吗?
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 条回复,欢迎继续交流。
正在加载回复...