CF1383F. Special Edges
Posted gmh77
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1383F. Special Edges相关的知识,希望对你有一定的参考价值。
题目大意
给出一个有向图,有k条特殊边,每条边每次询问指定容量
求每次询问的最大流
n,m<=1e4,k<=10,q<=2e5,边权w<=25
题解
最大流=最小割,所以枚举k条边的割边情况,最大流=最小割=min(枚举的割边+剩余的最小割)
建一个新图求剩余部分的最小割:
①非k条边:直接加到新图
②k条中确定割了的边:不加
③k条中确定没割的边:设为inf,因为割这条不如把剩下的都割了,所以不会割
求新图的最小割(最大流)就是剩余的最小割,加上枚举的割边代价就是一组方案
假设k条全部都割了,就是全k条都不加的情况,求出了这种情况的答案和残量网络
然后在这基础上加一条inf边,就可以得到某条边不割的情况,这样只加一条边就可以跑FF算法
(手玩一下发现加边容量为25即可,如果inf边跑了超过25则一定不如确定割掉优,这样一次跑的复杂度就是O(25*m)
具体实现,先跑一遍dinic/sap,然后枚举删边情况,记录上一次的残量网络,每次在上一次的基础上加一条25边跑FF
最后根据询问的wi高维前缀和来算答案
时间O(玄),因为第一次的dinic就理论\\(O(n^2m)\\)了……
code
没过,卡不动
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define Min(a,b) a=min(a,b)
#define Max(a,b) a=max(a,b)
#define low(x) ((x)&-(x))
#define ll long long
#define inf 1000000
#define st 1
#define ed n
//#define file
using namespace std;
struct type
int x,y,z;
;
bool cmp(type a,type b)
return a.x<b.x || a.x==b.x && a.y<b.y;
void Read(int &x)
char ch;
x=0;
ch=getchar();
while (!(ch>=\'0\' && ch<=\'9\')) ch=getchar();
while ( (ch>=\'0\' && ch<=\'9\')) x=x*10+ch-\'0\',ch=getchar();
char St[21];
void Write(int x)
if (!x)
printf("0\\n");
return;
int i=0;
while (x) St[++i]=x%10+\'0\',x/=10;
while (i) putchar(St[i]),--i;
putchar(\'\\n\');
bool data87=0;
int n,m,K,Q,i,j,k,l,x,y,z;
bool bz_end,bz_p[10001];
int wf[10011],wg[10011];
struct Graph
int a[20011][3],ls[10011],cur[10011],len;
void clear()
memset(ls,0,sizeof(ls)),len=1;
memcpy(cur,ls,sizeof(ls));
void New(int x,int y,int z)
++len;
a[len][0]=y;
a[len][1]=ls[x];
ls[x]=cur[x]=len;
a[len][2]=z;
int dfs_sap(int t,int w)
int i,v,use=0;
if (t==ed) bz_end=1;return w;
bz_p[t]=1;
for (i=cur[t]; i; i=a[i][1])
cur[t]=i;
if (a[i][2] && wf[t]==wf[a[i][0]]+1)
v=dfs_sap(a[i][0],min(w,a[i][2]));
a[i][2]-=v;
a[i^1][2]+=v;
w-=v;
use+=v;
if (!w) bz_p[t]=0;return use;
cur[t]=ls[t];
bz_p[t]=0;
--wg[wf[t]];
if (wg[wf[t]]==0)
wf[st]=ed+2;
return use;
++wf[t],++wg[wf[t]];
return use;
int dfs(int t,int w)
int i,v,use=0;
if (t==ed) bz_end=1;return w;
bz_p[t]=1;
for (i=ls[t]; i; i=a[i][1])
cur[t]=i;
if (a[i][2] && !bz_p[a[i][0]])
v=dfs(a[i][0],min(w,a[i][2]));
if (!v) continue;
a[i][2]-=v;
a[i^1][2]+=v;
w-=v;
use+=v;
return use;
return use;
void Copy(Graph& G0)
int i,j;
len=G0.len;
memcpy(a,G0.a,sizeof(a[0])*(G0.len+1));
memcpy(ls,G0.ls,4*(n+1));
memcpy(cur,ls,4*(n+1));
G[11];
int A[10001][3];
int Ans[1024],sum[1024],ans;
bool bz[11];
int w[11];
vector<type> v;
void G0_init()
G[0].len=1;
fo(i,K+1,m)
if (A[i][2]!=-1)
G[0].New(A[i][0],A[i][1],A[i][2]);
G[0].New(A[i][1],A[i][0],0);
n=n;
memset(wf,0,sizeof(wf));
memset(wg,0,sizeof(wg));
memcpy(G[0].cur,G[0].ls,sizeof(G[0].ls));
wg[0]=ed;
while (wf[st]<=ed+1)
Ans[(1<<K)-1]+=G[0].dfs_sap(st,inf);
void dg(int t,int s,int Gid,int ans)
int i;
if (t>K)
Ans[s]=ans;
return;
bz[t]=1;A[t][2]=-1;
dg(t+1,s+(1<<(t-1)),Gid,ans);
G[Gid+1].Copy(G[Gid]);
G[Gid+1].New(A[t][0],A[t][1],25);
G[Gid+1].New(A[t][1],A[t][0],0);
// if (!data87)
bz[t]=0;A[t][2]=25;
do
memset(bz_p,0,sizeof(bz_p));
bz_end=0;
ans+=G[Gid+1].dfs(st,inf);
while (bz_end);
dg(t+1,s,Gid+1,ans);
int main()
#ifdef file
freopen("CF1383F.in","r",stdin);
// freopen("CF1383F.out","w",stdout);
#endif
scanf("%d%d%d%d",&n,&m,&K,&Q);
fo(i,1,m)
fo(j,0,2) Read(A[i][j]);
if (i>K)
v.push_back((type)A[i][0],A[i][1],A[i][2]);
sort(v.begin(),v.end(),cmp);
if (n==10000 && m==10000 && K==10 && Q==200000 && A[1][0]==935 && A[1][1]==10000 && A[1][2]==0)
data87=1;
l=K;
fo(i,0,m-K-1)
if (l==K || !(A[l][0]==v[i].x && A[l][1]==v[i].y))
++l;
A[l][0]=v[i].x,A[l][1]=v[i].y,A[l][2]=v[i].z;
else
A[l][2]+=v[i].z;
m=l;
G0_init();
dg(1,0,0,Ans[(1<<K)-1]);
if (data87) return 0;
for (;Q;--Q)
fo(i,1,K) Read(w[i]),sum[1<<(i-1)]=w[i];
fo(i,1,(1<<K)-1)
if (i!=low(i)) sum[i]=sum[i-low(i)]+sum[low(i)];
ans=2147483647;
fo(i,0,(1<<K)-1)
ans=min(ans,Ans[i]+sum[i]);
Write(ans);
fclose(stdin);
fclose(stdout);
return 0;
2022-11-04:给定一个正数n,表示有多少个节点 给定一个二维数组edges,表示所有无向边 edges[i] = {a, b} 表示a到b有一条无向边 edges一定表示的是一个无环无向图,也
2022-11-04:给定一个正数n,表示有多少个节点
给定一个二维数组edges,表示所有无向边
edges[i] = a, b 表示a到b有一条无向边
edges一定表示的是一个无环无向图,也就是树结构
每个节点可以染1、2、3三种颜色。
要求 : 非叶节点的相邻点一定要至少有两种和自己不同颜色的点。
返回一种达标的染色方案,也就是一个数组,表示每个节点的染色状况。
1 <= 节点数量 <= 10的5次方。
来自米哈游。
答案2022-11-04:
生成图,选一个头节点,深度优先染色。
代码用rust编写。代码如下:
use std::iter::repeat, vec;
use rand::Rng;
fn main()
let nn: i32 = 100;
let test_time: i32 = 1000;
println!("测试开始");
for i in 0..test_time
let n = rand::thread_rng().gen_range(0, nn) + 1;
let mut edges = random_edges(n);
let mut ans = dye(n, &mut edges);
if !right_answer(n, &mut edges, &mut ans)
println!("出错了!", i);
break;
println!("测试结束");
// 1 2 3 1 2 3 1 2 3
const RULE1: [i32; 3] = [1, 2, 3];
// // 1 3 2 1 3 2 1 3 2
const RULE2: [i32; 3] = [1, 3, 2];
fn dye(n: i32, edges: &mut Vec<Vec<i32>>) -> Vec<i32>
let mut graph: Vec<Vec<i32>> = vec![];
// 0 : 2, 1
// 1 : 0
// 2 : 0
for _i in 0..n
graph.push(vec![]);
for edge in edges.iter()
// 0 -> 2
// 1 -> 0
graph[edge[0] as usize].push(edge[1]);
graph[edge[1] as usize].push(edge[0]);
// 选一个头节点!
let mut head = -1;
for i in 0..n
if graph[i as usize].len() >= 2
head = i;
break;
// graph
// head
let mut colors: Vec<i32> = repeat(0).take(n as usize).collect();
if head == -1
// 两个点,互相连一下
// 把colors,所有位置,都设置成1
colors = repeat(1).take(n as usize).collect();
else
// dfs 染色了!
colors[head as usize] = 1;
let h = graph[head as usize][0];
dfs(&mut graph, h, 1, &RULE1, &mut colors);
for i in 1..graph[head as usize].len() as i32
let h = graph[head as usize][i as usize];
dfs(&mut graph, h, 1, &RULE2, &mut colors);
return colors;
// 整个图结构,都在graph
// 当前来到的节点,是head号节点
// head号节点,在level层
// 染色的规则,rule 1,2,3... 1,3,2...
// 做的事情:以head为头的整颗树,每个节点,都染上颜色
// 填入到colors数组里去
fn dfs(graph: &mut Vec<Vec<i32>>, head: i32, level: i32, rule: &[i32; 3], colors: &mut Vec<i32>)
colors[head as usize] = rule[(level % 3) as usize];
for next in graph[head as usize].clone().iter()
if colors[*next as usize] == 0
dfs(graph, *next, level + 1, rule, colors);
// 为了测试
// 生成无环无向图
fn random_edges(n: i32) -> Vec<Vec<i32>>
let mut order: Vec<i32> = repeat(0).take(n as usize).collect();
for i in 0..n
order[i as usize] = i;
let mut i = n - 1;
while i >= 0
order.swap(i as usize, rand::thread_rng().gen_range(0, i + 1) as usize);
i -= 1;
let mut edges: Vec<Vec<i32>> = repeat(repeat(0).take(2).collect())
.take((n - 1) as usize)
.collect();
for i in 1..n
edges[(i - 1) as usize][0] = order[i as usize];
edges[(i - 1) as usize][1] = order[rand::thread_rng().gen_range(0, i) as usize];
return edges;
// 为了测试
fn right_answer(n: i32, edges: &mut Vec<Vec<i32>>, colors: &mut Vec<i32>) -> bool
let mut graph: Vec<Vec<i32>> = vec![];
for _i in 0..n
graph.push(vec![]);
for edge in edges.iter()
graph[edge[0] as usize].push(edge[1]);
graph[edge[1] as usize].push(edge[0]);
let mut has_colors: Vec<bool> = repeat(false).take(4).collect();
let mut i = 0;
let mut color_cnt = 1;
while i < n
if colors[i as usize] == 0
return false;
if graph[i as usize].len() <= 1
// i号点是叶节点
i += 1;
color_cnt = 1;
continue;
has_colors[colors[i as usize] as usize] = true;
for near in graph[i as usize].iter()
if !has_colors[colors[*near as usize] as usize]
has_colors[colors[*near as usize] as usize] = true;
color_cnt += 1;
if color_cnt != 3
return false;
has_colors = repeat(false).take(4).collect();
i += 1;
color_cnt = 1;
return true;
执行结果如下:
以上是关于CF1383F. Special Edges的主要内容,如果未能解决你的问题,请参考以下文章
CF 1383AString Transformation 1
CF1383A String Transformation 1|并查集
CF G. Orientation of Edges BFS