元旦老人与丛林
作死写一遍没保存
这题很经典大概吧,收获很多
-
退流:
网络流中如果要删去(u,v)边,则可以跑dinic(t,v,inf),dinic(u,s,inf),从而达到退流的效果,然后在把u->v的正反向边权设为0,达到删去边的效果。注意如果有最大流相关的操作,不要忘记maxflow加或减退的流量
-
最大权闭合子图:
如果一个图,需要选择的边对应的点都包含在图里面,则成为这个图的子图。每个点有正负权值,需要选取最大的权值的子图则成为最大权闭合子图。可以把S连向正权值的点,负权值点连向T,点与点如果有边权值为inf,显然,最小割必然在连向S或T的边中,而最小割|最大流就是问题的答案。
对应的还有最大密度子图。
-
对于这题:
关键是得出 E-2*V<-2 则问题才有解这个结论,边变为点权为1,点权为-2,枚举每一个点,把该点权值变为0,依次求最大闭合子图,如果存在不满足等式条件,输出No return就完事了。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=8e3+5,inf=1e9+5;
int n,m,x,y;
int totn,source,target;
int dis[N],flow[N],pos[N];
bool use[N];
int maxflow;
int level[N];
struct node
{
int link;
int w;
int position;
};
vector<node> f[N];
void add_edge(int x,int y,int z)
{
f[x].push_back((node){y, z,(int)f[y].size()});
f[y].push_back((node){x, 0,(int)f[x].size()-1});// 获取x在y的第几条边
}
int dfs(int x,int flow)
{
int ans = 0;
if(x==target||flow==0)
return flow;
for(auto &i:f[x])//结构体无法在外部改变,外面只是创建了一个临时变量(相当结构体内部变量是私有属性)
{
if(i.w>0&&level[i.link]==level[x]+1)// 保证边权不为0 且按照深度dfs
{
int d = dfs(i.link, min(flow, i.w)); // 搜索,flow是最小的所以是min
if(d==0)
level[i.link] = 0;
if(d>0)
{
i.w -= d;//正向边减少
f[i.link][i.position].w += d;// 反向边增加
flow -= d;
ans += d;
if(flow==0)
break;
}
}
}
return ans;
}
bool bfs(int s,int t)
{
queue <int> q;
q.push(s);
memset(level, -1, sizeof(level));
level[s] = 0;
while(!q.empty())
{
int temp = q.front();
q.pop();
for(auto &i:f[temp])
{
if(i.w==0||level[i.link]!=-1)
continue;
level[i.link] = level[temp] + 1;
q.push(i.link);
}
}
if(level[t]!=-1)
return 1;
return 0;
}
int dinic(int s,int t,int flow)
{
long long ans = 0;
while(bfs(s,t))
ans += dfs(s,flow);
return ans;
}
int main()
{
scanf("%d %d",&n,&m);
source=0;
target=n+m+1;
bool flag=0;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d %d",&x,&y);
if(x==y)
{
flag=1;
continue;
}
add_edge(i+n,y,inf);
add_edge(i+n,x,inf);
}
if(flag==1)
{
printf("No\n");
return 0;
}
for(int i=1;i<=m;i++)
add_edge(source,i+n,1);
for(int i=1;i<=n;i++)
add_edge(i,target,2);
// for(int i=0;i<=m+n+1;i++)
// {
// printf("i:%d\n",i);
// for(auto j:f[i])
// printf("???%d %d",j.link,j.w);
// printf("\n");
// }
int maxflow=dinic(source,target,inf);
if(m-maxflow>0)
{
printf("No\n");
return 0;
}
for(int i=1;i<=n;i++)
{
// source=n+m+1;
// target=n+m+1;
// maxflow-=dinic(source,target,inf);
source=i;
target=0;
maxflow-=dinic(i,0,inf);
(f[i][int(f[i].size())-1]).w=0;
(f[n+m+1][f[i][(int)f[i].size()-1].position]).w=0;
source=0;
target=n+m+1;
maxflow+=dinic(0,n+m+1,inf);
if(m-maxflow>0)
{
printf("No\n");
return 0;
}
f[i][int(f[i].size())-1].w=2;
}
printf("Yes\n");
return 0;
}
/*
5 4
1 2
2 3
1 5
2 4
*/
$道路千万条,点赞第一条;阅读不规范,笔者两行泪$