P9705 「TFOI R1」Unknown Graph 题解
这道题的正解是网络流。但是这个正解实在是不太好想,因为题意是让你构造一个满足输入要求的图,并没有出现一星半点儿能让人联想到网络流的线索。
那么这道题怎么建图呢?
首先,当我们看见每个点都有两个描述——入度和出度。既然如此麻烦,何不拆点建图?嗯,有道理。步骤如下:
- 将入度点
连向超级汇点,长度为这个点的入度数(即 ); - 将出度点
连向超级源点,长度为这个点的出度数(即 ); - 将入度点连向所有出度点。注意不能自环,不能忽略特殊限制。
然后就建完图了。
在此基础上跑一遍网络流即可。为什么呢?因为你在跑网络流的时候,如果选择了
今天破例贴个代码吧。用的某 Dinic,并没有加当前弧优化。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,s,t,x,y,z,ans,cnt=1,dist[5000000],head[5000000],xz[1001][1001];
struct node
{
int start;
int to;
int v;
int next;
}a[5000000];
void add(int x,int y,int z)
{
a[++cnt].start=x;
a[cnt].to=y;
a[cnt].v=z;
a[cnt].next=head[x];
head[x]=cnt;
a[++cnt].start=y;
a[cnt].to=x;
a[cnt].v=0;
a[cnt].next=head[y];
head[y]=cnt;
}
int bfs()
{
for(int i=s;i<=t;++i) dist[i]=0x7fffffff;
queue<int>q;
q.push(s);
dist[s]=0;
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i;i=a[i].next)
{
int y=a[i].to;
if(a[i].v>0&&dist[y]==0x7fffffff)
{
q.push(y);
dist[y]=dist[x]+1;
if(y==t) return 1;
}
}
}
return 0;
}
int dfs(int x,int sum)
{
if(x==t) return sum;
int k,res=0;
for(int i=head[x];i&∑i=a[i].next)
{
int y=a[i].to;
if(a[i].v>0&&dist[y]==dist[x]+1)
{
k=dfs(y,min(sum,a[i].v));
if(k==0) dist[y]=0x7fffffff;
a[i].v-=k;
a[i^1].v+=k;
res+=k;
sum-=k;
}
}
return res;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie();
cin>>n;
s=0;
t=2*n+1;
for(int i=1;i<=n;++i)
{
cin>>x;
add(i+n,t,x);
}
for(int i=1;i<=n;++i)
{
cin>>x;
add(s,i,x);
}
cin>>m;
for(int i=1;i<=m;++i)
{
cin>>x>>y;
xz[x][y]=1;
}
for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(i!=j&&!xz[i][j]) add(i,j+n,1);
while(bfs())
{
ans+=dfs(s,0x7fffffff);
}
cout<<ans<<endl;
for(int i=4*n-1;i<=cnt;++i)
{
if(a[i].start==s||a[i].to==t||i%2==1) continue;
if(a[i].v==0) cout<<a[i].start<<" "<<a[i].to-n<<"\n";
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】