题解:P5786 [CQOI2008] 传感器网络
1.题解:CF1941G Rudolf and Subway2.题解:ssy的队列
3.题解:P5786 [CQOI2008] 传感器网络
4.题解:AT_arc116_e [ARC116E] Spread of Information题意
从一个
输出满足题意的节点的父亲,要求字典序最小。
思路
我们肯定要先把最小值求出来。
很容易看出是 拆点 + 二分答案求解,这里要注意的是拆完的两个点是不用连起来的,将做为儿子的点与源点连边,权值为
然后就是 蒟蒻不会二分验证 。
从
注意
这道题要保证字典序最小,而控制中心用
代码
剩下要注意的就看代码吧,写了注释
我好像是写的最麻烦的那个
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10,inf=1e9;
int n,m,s,t,tot=1,ans,_,fa[N];
int head[N],nxt[N],to[N],val[N];
int dep[N],cur[N],g[N],gg[N],fl[N];
//_,g,gg 分别用于暂存 tot,val,head方便回溯
vector<int>v[N],mp[N];
//Dinic 板子
inline void add(int u,int v,int w)
{
nxt[++tot]=head[u];
head[u]=tot;
to[tot]=v;
val[tot]=w;
return ;
}
inline void insert(int u,int v,int w)
{
add(u,v,w);
add(v,u,0);
return ;
}
inline bool bfs()
{
for(int i=1;i<=t;i++)
dep[i]=0;
queue<int>q;
q.push(s);
dep[s]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
cur[x]=head[x];
for(int i=head[x],y;i;i=nxt[i])
{
y=to[i];
if(val[i]&&!dep[y])
{
dep[y]=dep[x]+1;
q.push(y);
}
}
}
return dep[t];
}
inline int dfs(int x,int flow)
{
if(x==t)
return flow;
int res=flow;
for(int i=cur[x],y,k;i&&res;i=nxt[i])
{
y=to[i];
cur[x]=i;
if(val[i]&&dep[y]==dep[x]+1)
{
k=dfs(y,min(res,val[i]));
val[i]-=k;
val[i^1]+=k;
res-=k;
}
}
return flow-res;
}
//暂存
inline void init()
{
for(int i=1;i<=tot;i++)
g[i]=val[i];
for(int i=1;i<=t;i++)
gg[i]=head[i];
_=tot;
return ;
}
//回溯
inline void tini()
{
for(int i=1;i<=tot;i++)
val[i]=g[i];
for(int i=1;i<=t;i++)
head[i]=gg[i];
tot=_;
return ;
}
int main()
{
cin>>n;
s=2*n+1;
t=2*n+2;
char ch;
for(int i=1;i<=n;i++)
{
insert(s,i,1);
cin>>ch;
if(ch=='Y')
{
insert(i,t,1); //这里向汇点连边的时候也要存进 vector 里!!!
v[i].push_back(t);
mp[i].push_back(tot-1);
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>ch;
if(ch=='Y')
{
insert(i,n+j,1);
v[i].push_back(j);
mp[i].push_back(tot-1);
}
}
for(int i=1;i<=n;i++) //写的好唐,其实不用这样的
sort(v[i].begin(),v[i].end());
init();
int l=0,r=1000,mid,res;
while(l<=r) // 二分求最小值
{
mid=l+r>>1;
for(int i=1;i<=n;i++)
insert(n+i,t,mid);
ans=0;
while(bfs())
ans+=dfs(s,inf);
tini();
if(ans==n)
{
r=mid-1;
res=mid;
}
else
l=mid+1;
}
for(int i=1;i<=n;i++)
insert(n+i,t,res);
for(int i=1;i<=n;i++)
{
for(auto it : mp[i])
val[it]=0; //清空所有向可能父亲的连边
init();
for(auto it : v[i])
{
int j=it==t?n+2:it;
insert(i,n+j,1);
ans=0;
while(bfs())
ans+=dfs(s,inf);
tini();
if(ans==n) //确定答案后把边加进去
{
fa[i]=j;
insert(i,n+j,1);
init();
break;
}
}
}
for(int i=1;i<=n;i++)
{
if(fa[i]==n+2) // 写的唐了,也不用这么写的
fa[i]--;
printf("%d ",fa[i]-1);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通