2023五一外出学习整理(图论
Day1:
上午:
引入:
对任意两个元素a,b之间关系(a,b)的取值仅为 True 或者 False,可以考虑使用图来抽象。这样我们称一个元素 a 为一个结点,(a,b)== True 则称结点 a,b 间有连边,否则 a,b 间没有连边。
问题转化:一张奇数个点的图 G,证明存在一个点度数为偶数。
转化为更强的问题为:给定一张奇数个点的图 G,证明度数为偶数的点的个数为奇数。
(相反的问题:给定一张奇数个点的图 G,证明度数为奇数的结点的个数为偶数。)
证明:考虑所有点的度数和,由于一条边会被计算到两个结点的度数上,故其必定为偶数。(小学数学易得结论?)
Ex.1:首先可证 n-1 个点与除它之外 n-2 个点连边所以可连 (n-1)(n-2)/2 条边,因此可得 n 个点和至少 ((n-1)(n-2)/2)+1 条边的图是连通图。
Ex.2:
由图可得,对于任意一个图,可将其分为若干个连通块,连通块内部各点都相连,因此其补图原来的连通块内各点于其他各连通块各点相连,因此一定是联通的。
Ex.3:
任意两边至少有一个点是重合的,即为如图:
因此当为完全图时,每点度数>=2,因此不可能为星星,反之亦然。
Ex.4:***
Ex.5:分类讨论,
当存在度数为一的点时,删掉度数为一的点剩下的图依旧是连通图。
当不存在时,选择任意一点为起点,计算其他点与起点的距离,删掉距离起点最远的点后,图依旧为连通图。
欧拉回路和哈密顿回路:
1)考虑一个度数为奇数的点,因为它的所有邻边均要遍历恰好一次,故其必须为欧
拉路径的起点或终点。因此可以立即推出,一张存在欧拉路径的图恰好有两个度数为奇数
的点,存在欧拉回路的图没有度数为奇数的点。
2)任意两个回路,可以拼成一个大的回路。
由这两个观察可以发现,Fact 1是存在欧拉路径或者欧拉回路的充要条件。
反证法,假设没有哈密顿回路。
我们由图 G 构造出一个新的没有哈密顿回路的图 G',具体的,令 G'=G,对于每条不在图 G 中的边,如果加入 G' 后不会产生哈密顿回路,则加入,该构造的顺序不重要。
此时我们得到了一个图 G',再加入任何一条边都会得到一条哈密顿回路,并且由于我们仅加入了新的边,所有结点的度数任然大于等于 n/2。
假设 (v1,vn) 这条边不在 G' 中,我们知道必定存在一条哈密顿路径 v1,v2,...,vn 考虑 (v1,vi) 有一条边,则 (vi-1,vn) 必定不能有边,否则可以构造出一条哈密顿回路。
因为这样的 vi 至少有 n/2 个,从而这样的 vi-1 也至少有 n/2 个,又由于 vn 不能和自己连边,故而它至多与 n-n/2-1 个点连边,<=n/2 ,因此与定理矛盾,因此假设不成立。
Ex.6:因为两数互质,因此间隔至少为2,又因为有 n+1,个小于等于 2n 的正整数,所以显然,存在两个数互质。
Ex.7:...
Ex.8:将棋盘进行黑白染色和蓝红染色
Ex.9:Luogu P1341
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 1e3+5; 7 int n,sum,dis[N][N]; 8 char in[N],a[N]; 9 inline int read() 10 { 11 int x=0,f=1;char ch=getchar(); 12 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 13 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 14 return x*f; 15 } 16 17 void Find(int i) 18 { 19 for (int j=1;j<=150;j++) 20 { 21 if(dis[i][j]>0) 22 { 23 dis[i][j]--; 24 dis[j][i]--; 25 Find(j); 26 } 27 } 28 a[++sum]=i; 29 return ; 30 } 31 32 int main() 33 { 34 n=read(); 35 for (int i=1;i<=n;i++) 36 { 37 string s; 38 cin>>s; 39 dis[s[0]][s[1]]++; 40 dis[s[1]][s[0]]++; 41 in[s[0]]++; 42 in[s[1]]++; 43 } 44 int h=0; 45 int cnt=0; 46 for (int i=1;i<=150;i++) 47 { 48 if(in[i] & 1) 49 { 50 cnt++; 51 if(!h) 52 h=i; 53 } 54 } 55 if(!h) 56 { 57 for (int i=0;i<150;i++) 58 { 59 if(in[i]) 60 { 61 h=i; 62 break; 63 } 64 } 65 } 66 if(cnt && cnt!=2) 67 { 68 cout<<"No Solution"; 69 exit(0); 70 } 71 Find(h); 72 if(sum<n+1) 73 { 74 cout<<"No Solution"; 75 exit(0); 76 } 77 for(int i=sum;i>=1;i--) 78 cout<<a[i]; 79 return 0; 80 //Amireux_35 81 }
图的储存和遍历:
1)邻接矩阵: .........没啥可说的
2)邻接表:
vector :
1 #include <vector> 2 vector<int> Edge[1000]; 3 // Edge[i] 是一个一维数组,存了所有 i 能到的点 4 void add(int u, int v) // 插入一条 (u,v) 的边 5 { 6 Edge[u].push_back(v); 7 Edge[v].push_back(u); 8 } 9 void search(int u) // 遍历 u 的所有邻边 10 { 11 for ( int i = 0; i < Edge[u].size(); i++ ) 12 //Edge[u].size() 是unsigned int,0-1=2^32-1 13 { 14 int v = Edge[u][i]; 15 //(u,v) 有一条边 16 ...... 17 } 18 }
链式前向星:
1 int Begin[1000], Next[1000], To[1000], e; 2 void add(int u, int v) // 插入一条 (u,v) 的边 3 { 4 To[++ e] = v; 5 Next[e] = Begin[u]; 6 Begin[u] = e; 7 } 8 void search(int u) 9 { 10 for ( int i = Begin[u]; i; i = Next[i] ) // 遍历 u 的所有邻边 11 { 12 int v = To[i]; 13 ... 14 } 15 }
注:这是ljf的代码,本人等习惯用结构体。
Ex.10:CF 1472C
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ll long long 5 const int N = 1e6+5; 6 int T,n,a[N]; 7 bool vis[N]; 8 vector<int> edge[N]; 9 inline int read() 10 { 11 int x=0,f=1;char ch=getchar(); 12 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 13 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 14 return x*f; 15 } 16 17 int dfs(int u) 18 { 19 if(u>n || vis[u]) 20 return 0; 21 vis[u]=true; 22 if(edge[u].size()==1) 23 return a[u]+dfs(edge[u][0]); 24 return a[u]; 25 } 26 27 int main() 28 { 29 T=read(); 30 while (T--) 31 { 32 int ans=0; 33 n=read(); 34 for (int i=1;i<=n;i++) 35 { 36 vis[i]=false; 37 edge[i].clear(); 38 } 39 for (int i=1;i<=n;i++) 40 { 41 cin>>a[i]; 42 edge[i].push_back(i+a[i]); 43 } 44 for (int i=1;i<=n;i++) 45 ans=max(ans,dfs(i)); 46 cout<<ans<<"\n"; 47 } 48 return 0; 49 //Amireux_35 50 }
二分图:
显然,二分图 G 存在完美匹配的必要条件是 ιAι = ιBι
Ex.11:Luogu P3386
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ll long long 5 const int N = 1e6+5; 6 int n,m,p,ans,cnt,e_cnt,sum[N],dfn[N],head[N]; 7 struct node{ 8 int v; 9 int nxt; 10 }e[N]; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 15 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 16 return x*f; 17 } 18 19 void add(int u,int v) 20 { 21 e[++e_cnt].v=v; 22 e[e_cnt].nxt=head[u]; 23 head[u]=e_cnt; 24 } 25 26 bool dfs(int u,int t) 27 { 28 for (int i=head[u];i;i=e[i].nxt) 29 { 30 int v=e[i].v; 31 if(dfn[v]!=t) 32 { 33 dfn[v]=t; 34 if(!sum[v] || dfs(sum[v],t)) 35 { 36 sum[v]=u; 37 return true; 38 } 39 } 40 } 41 return false; 42 } 43 44 int main() 45 { 46 n=read(); 47 m=read(); 48 p=read(); 49 for (int i=1;i<=p;i++) 50 { 51 int u=read(); 52 int v=read(); 53 if(u>n || v>m) 54 continue; 55 add(u,v); 56 } 57 for (int i=1;i<=n;i++) 58 if(dfs(i,++cnt)) 59 ans++; 60 cout<<ans; 61 return 0; 62 }
Ex.12:CF 1764C
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define int long long 6 const int N = 1e6+5; 7 int T,n,a[N],sum[N]; 8 inline int read() 9 { 10 int x=0,f=1;char ch=getchar(); 11 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 12 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 13 return x*f; 14 } 15 16 signed main() 17 { 18 T=read(); 19 while (T--) 20 { 21 int cnt=0; 22 int ans=0; 23 n=read(); 24 for (int i=1;i<=n;i++) 25 { 26 a[i]=read(); 27 sum[a[i]]++; 28 } 29 sort(a+1,a+1+n); 30 for (int x=1;x<=n;x++) 31 { 32 if(a[x]==a[x-1]) 33 continue; 34 cnt+=sum[a[x]]; 35 if(cnt==n) 36 ans=max(ans,n/2); 37 else 38 ans=max(ans,cnt*(n-cnt)); 39 } 40 cout<<ans<<"\n"; 41 for (int i=1;i<=n;i++) 42 sum[a[i]]--; 43 // memset(sum,0,sizeof sum); 44 } 45 return 0; 46 //Amireux_35 47 }
一份 vector 的使用说明:
1 #include <vector> // 头文件 2 vector<int> a; // 等价于定义一个 int a[] 的数组 3 int a[100]; 4 vector<int> a(100); 5 printf("%d\n", a.size()); // 100 6 a.push_back(1); 7 printf("%d\n", a.size()); // 101 8 a.push_back(x); // 在 a 的最末尾插入一个值为 x 的元素 9 a[i] // 访问 a 的第 i 个元素 10 a.size() // 返回 a 的元素个数(类型为 unsigned int) 11 a.pop() // 移除 a 的最末尾的元素 12 a.empty() // 返回 a 的 size 是否非零 (True or False) 13 a.resize(10) // 修改 a 的 size 为 10
下午:(树)
基本知识:
直观上来说,树等价于没有环的连通图。
树有非常好的性质:
1)任意两点间存在唯一的路径,不存在回路。
2)树一定存在叶结点,即 deg==1 的结点。
树作为一种特殊的图,研究他的重要意义是,在这些特殊性质下,我们可以解决一些在图中无法解决的问题。------ljf
树的储存通常使用与图相同的储存方式,而遍历通常使用DFS
1 DFS(root, 0); // root 表示整棵树的根 2 3 void DFS(int u, int from) 4 { 5 ...... 6 for ( int i = 0; i < Edge[u].size(); ++i ) 7 { 8 int v = Edge[u][i]; 9 if ( v == from ) 10 continue ; 11 DFS(v, u); 12 } 13 ...... 14 }
Ex.1:CF 522A
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 401; 7 int n,cnt,ans,dep[N]; 8 string a,b; 9 map<string,int> mp; 10 vector<vector<int>> g; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 15 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 16 return x*f; 17 } 18 19 void change(string &a) 20 { 21 int len=a.size(); 22 for (int i=0;i<len;i++) 23 { 24 if(a[i]>='A' && a[i]<='Z') 25 { 26 a[i]-='A'; 27 a[i]+='a'; 28 } 29 } 30 } 31 32 void dfs(int x) 33 { 34 for (int i=0;i<g[x].size();i++) 35 { 36 int v=g[x][i]; 37 dep[v]=dep[x]+1; 38 dfs(v); 39 } 40 ans=max(ans,dep[x]); 41 } 42 43 int main() 44 { 45 n=read(); 46 g.resize(2*n+3); 47 for (int i=1;i<=n;i++) 48 { 49 cin>>a>>b>>b; 50 change(a); 51 change(b); 52 if(!mp.count(a)) 53 mp[a]=++cnt; 54 if(!mp.count(b)) 55 mp[b]=++cnt; 56 g[mp[a]].push_back(mp[b]); 57 } 58 for (int i=1;i<=cnt;i++) 59 { 60 if(!dep[i]) 61 { 62 dep[i]=1; 63 dfs(i); 64 } 65 } 66 cout<<ans; 67 return 0; 68 //Amireux_35 69 }
Ex.2:CF 115A
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 1e6+5; 7 int n,ans,fa[N]; 8 inline int read() 9 { 10 int x=0,f=1;char ch=getchar(); 11 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 12 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 13 return x*f; 14 } 15 16 int Find(int x) 17 { 18 int cnt=0; 19 while (x!=-1) 20 { 21 x=fa[x]; 22 cnt++; 23 } 24 return cnt; 25 } 26 27 int main() 28 { 29 n=read(); 30 for (int i=1;i<=n;i++) 31 fa[i]=read(); 32 for (int i=1;i<=n;i++) 33 ans=max(ans,Find(i)); 34 cout<<ans; 35 return 0; 36 //Amireux_35 37 }
直径和重心:
称树的直径为树上最长的一条路径,树的重心为 删去这个点后,最大的子树最小
1 int DFS(int u, int from) 2 { 3 int Max = 0, Maxx = 0; 4 for ( int i = 0; i < Edge[u].size(); ++ i ) 5 { 6 int v = Edge[u][i]; 7 if ( v == from ) continue ; 8 int dis = DFS(v, u); 9 if ( dis > Max ) { Maxx = Max; Max = dis; } 10 else if ( dis > Maxx ) Maxx = dis; 11 } 12 ans = max(ans, Max + Maxx + 1); 13 return Max + 1; 14 }
1 int ans = n + 1, pos = 0; 2 int DFS(int u, int from) 3 { 4 int size = 1, Max = 0; 5 for ( int i = 0; i < Edge[u].size(); ++ i ) 6 { 7 int v = Edge[u][i]; 8 if ( v == from ) continue ; 9 int x = DFS(v, u); 10 size += x; 11 Max = max(Max, x); 12 } 13 Max = max(Max, n - size); 14 if ( Max < ans ) { ans = Max, pos = u; } 15 return size; 16 }
Ex.3:CF 690C2
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 1e6+5; 7 int n,m,p,ans,e_cnt,dis[N],head[N]; 8 struct node{ 9 int v; 10 int nxt; 11 }e[N]; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 16 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 17 return x*f; 18 } 19 20 void add(int u,int v) 21 { 22 e[++e_cnt].v=v; 23 e[e_cnt].nxt=head[u]; 24 head[u]=e_cnt; 25 } 26 27 void dfs(int u,int frm) 28 { 29 int Max=0; 30 int Maxx=0; 31 for (int i=head[u];i;i=e[i].nxt) 32 { 33 int v=e[i].v; 34 if(v==frm) 35 continue; 36 dfs(v,u); 37 int w = dis[v]+1; 38 dis[u]=max(dis[u],w); 39 if(w>Max) 40 { 41 Maxx=Max; 42 Max=w; 43 } 44 else if (w>Maxx) 45 Maxx=w; 46 } 47 ans=max(ans,Max+Maxx); 48 } 49 50 int main() 51 { 52 n=read(); 53 m=read(); 54 for (int i=1;i<=m;i++) 55 { 56 int u=read(); 57 int v=read(); 58 add(u,v); 59 add(v,u); 60 } 61 dfs(1,0); 62 cout<<ans; 63 return 0; 64 }
最近公共祖先:
倍增算法
1 int LCA(int u, int v) 2 { 3 if ( dis[u] < dis[v] ) swap(u,v); 4 for ( int j = 20; j >= 0; -- j ) 5 if ( dis[f[u][j]] >= dis[v] ) u = f[u][j]; 6 if ( u == v ) return u; 7 for ( int j = 20; j >= 0; -- j ) 8 if ( f[u][j] != f[v][j] ) { u = f[u][j]; v = f[v][j]; } 9 return f[u][0]; 10 } 11 void INIT() 12 { 13 DFS(); // 使用 DFS 处理好 f[u][0] 和 dis[u] 14 for ( int j = 1; j <= 20; ++ j ) 15 for ( int i = 1; i <= n; ++ i ) 16 f[i][j] = f[f[i][j - 1]][j - 1]; 17 }
Tarjan算法
1 void DFS(int u, int from) 2 { 3 vis[u] = true; 4 for ( int i = 0; i < Edge[u].size(); ++ i ) 5 { 6 int v = Edge[u][i]; 7 if ( v == from ) continue ; 8 DFS(v, u); 9 Merge(u, v); // 并查集 10 } 11 for ( int i = 0; i < query[u].size(); ++ i ) // 在 u 点的查询列表 12 { 13 int v = query[u][i]; 14 if ( vis[v] == true ) ans[u][v] = Find(v); 15 //u,v 的查询答案是Find(v) 16 } 17 }
其它:
满二叉树是一种特殊的树,所有非叶结点都恰有两个子结点,它拥有更加优秀的性质:
Ex.4:CF 1741D
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 1e6+5; 7 int T,n,a[N]; 8 inline int read() 9 { 10 int x=0,f=1;char ch=getchar(); 11 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 12 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 13 return x*f; 14 } 15 16 int main() 17 { 18 T=read(); 19 while (T--) 20 { 21 n=read(); 22 clear(a); 23 for (int i=1;i<=n;i++) 24 a[i]=read(); 25 int cnt=0; 26 bool flag=false; 27 for (int i=2;i<=n;i<<=1) 28 { 29 for (int j=i;j<=n;j+=i) 30 { 31 if(a[j-(i>>1)]>a[j]) 32 { 33 swap(a[j-(i>>1)],a[j]); 34 cnt++; 35 } 36 if(a[j-(i>>1)]+(i>>1)!=a[j]) 37 { 38 cout<<-1<<"\n"; 39 flag=true; 40 break; 41 } 42 } 43 if(flag) 44 break; 45 } 46 if(flag) 47 continue; 48 cout<<cnt<<"\n"; 49 } 50 return 0; 51 //Amireux_35 52 } 53 54 /* 55 你考虑根左子树的数集合是A 56 右子树的数集合是B 57 那么无论你左右子树内部怎么转 58 这个集合是不会变的 59 所以你只有可能通过根的交换 60 来换A,B这两个完整的集合 61 所以有解当且仅当 62 A,B集合有一个全是小的数 63 另外一个全是大的数 64 然后递归做这个问题就行 65 */
Ex.5:CF 1675D
1 // Problem: CF1675D Vertical Paths 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1675D 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define ll long long 14 const int N = 2e6+5; 15 int T,n,ans,y[N],p[N],sum[N]; 16 bool vis[N]; 17 inline int read() 18 { 19 int x=0,f=1;char ch=getchar(); 20 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 21 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 22 return x*f; 23 } 24 25 int main() 26 { 27 T=read(); 28 while (T--) 29 { 30 ans=0; 31 n=read(); 32 for (int i=1;i<=n;i++) 33 { 34 vis[i]=false; 35 y[i]=1; 36 } 37 for (int i=1;i<=n;i++) 38 { 39 p[i]=read(); 40 if(p[i]!=i) 41 y[p[i]]=0; 42 } 43 for (int i=1;i<=n;i++) 44 if(y[i]) 45 ans++; 46 cout<<ans<<"\n"; 47 for (int i=1;i<=n;i++) 48 { 49 if(y[i]) 50 { 51 int now=i; 52 int cnt=0; 53 while (!vis[now]) 54 { 55 sum[++cnt]=now; 56 vis[now]=true; 57 if(p[now]==now) 58 break; 59 now=p[now]; 60 } 61 cout<<cnt<<"\n"; 62 for (int j=cnt;j>=1;j--) 63 cout<<sum[j]<<" "; 64 putchar('\n'); 65 } 66 } 67 putchar('\n'); 68 } 69 return 0; 70 //Amireux_35 71 }
Day2:
上午:
生成树问题:
DFS生成树:
对于任意一棵DFS生成树,其必定只有返祖边,没有横叉边,在求割点和强连通分量上方便很多。
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int N = 2e6+10; 5 int T,n,m,pre,flag,u[N],v[N],du[N],fa[N]; 6 inline int read() 7 { 8 int x=0,f=1;char ch=getchar(); 9 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 10 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 11 return x*f; 12 } 13 14 int Find(int x) 15 { 16 if(fa[x]==x) 17 return x; 18 return fa[x]=Find(fa[x]); 19 } 20 21 void init() 22 { 23 for (int i=1;i<=n;i++) 24 { 25 fa[i]=i; 26 du[i]=0; 27 } 28 } 29 30 int main() 31 { 32 T=read(); 33 while (T--) 34 { 35 vector<int> g; 36 pre=0; 37 flag=0; 38 n=read(); 39 m=read(); 40 init(); 41 for (int i=1;i<=m;i++) 42 { 43 u[i]=read(); 44 v[i]=read(); 45 int r1=Find(u[i]); 46 int r2=Find(v[i]); 47 if(r1!=r2) 48 { 49 fa[r1]=r2; 50 g.push_back(1); 51 } 52 else 53 { 54 // flag+=(++du[u[i]]==2); 55 // flag+=(++du[v[i]]==2); 56 if(++du[u[i]]==2) 57 flag++; 58 if(++du[v[i]]==2) 59 flag++; 60 g.push_back(0); 61 pre=i; 62 } 63 } 64 if(flag==3) 65 { 66 init(); 67 fa[Find(u[pre])]=Find(v[pre]); 68 for (int i=0;i<m;i++) 69 { 70 if(g[i]) 71 { 72 if(Find(u[i+1])==Find(v[i+1])) 73 { 74 g[i]=0; 75 break; 76 } 77 fa[Find(u[i+1])]=Find(v[i+1]); 78 } 79 } 80 g[pre-1]=1; 81 } 82 for (int i=0;i<g.size();i++) 83 cout<<g[i]; 84 putchar('\n'); 85 } 86 return 0; 87 //Amireux_35 88 } 89 90 /* 91 5 7 92 93 1 2 94 2 3 95 3 4 96 4 5 97 5 1 98 1 3 99 3 5 100 */
最小生成树:
1)Kruskal
贪心的思想,最小生成树肯定会尽可能的包含边权较小的边
考虑将将所有边权按从小到大排序,依次判断,若没有与之前选择的边一起构成环,则选择该边
正确性可以考虑对于边 e,若加入它后就不能变成最优的生成树 T,则 T+e 必定构成环
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 1e6+5; 7 int n,m,cnt,ans,e_cnt,fa[N]; 8 bool flag; 9 struct node{ 10 int u; 11 int v; 12 int w; 13 }e[N]; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 18 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 19 return x*f; 20 } 21 22 void add(int u,int v,int w) 23 { 24 e[++e_cnt].u=u; 25 e[e_cnt].v=v; 26 e[e_cnt].w=w; 27 } 28 29 int Find(int x) 30 { 31 if(x==fa[x]) 32 return x; 33 return fa[x]=Find(fa[x]); 34 } 35 36 bool cmp(node a,node b) 37 { 38 return a.w<b.w; 39 } 40 41 int main() 42 { 43 n=read(); 44 m=read(); 45 for (int i=1;i<=m;i++) 46 { 47 int x=read(); 48 int y=read(); 49 int w=read(); 50 add(x,y,w); 51 } 52 for (int i=1;i<=n;i++) 53 fa[i]=i; 54 sort(e+1,e+1+e_cnt,cmp); 55 for (int i=1;i<=e_cnt;i++) 56 { 57 int u=e[i].u; 58 int v=e[i].v; 59 int w=e[i].w; 60 int r1=Find(u); 61 int r2=Find(v); 62 if(r1!=r2) 63 { 64 fa[r2]=r1; 65 cnt++; 66 ans+=w; 67 } 68 if(cnt==n-1) 69 { 70 flag=true; 71 break; 72 } 73 } 74 if(flag) 75 cout<<ans; 76 else 77 puts("orz"); 78 return 0; 79 //Amireux_35 80 }
2)Prim
同样使用贪心的思想,Kruskal是加边,Prim是加点构成最小生成树
具体的,从任意结点开始,每次选择一个距离当前已选结点最近的点,选择并重复
最小生成树 - OI Wiki (oi-wiki.org)(严格次小/非严格次小生成树)
就是对于每一个仓库考虑与它有连边的非仓库的最短距离。
(为什么这么做是对的,因为除了仓库,所有点都是非仓库,那么如果最后选的点和最靠近它的仓库不是相邻的,那么必然可以在这个点与最靠近它的仓库的路径上选一个点使得答案可以更小)
然后把所有的取一个最小值,若所有仓库旁边都没有非仓库,那么输出 −1。
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int INF = 0x3f3f3f3f; 7 const int N = 1e6+5; 8 int n,m,k,e_cnt,head[N]; 9 bool vis[N]; 10 struct node{ 11 int v; 12 int w; 13 int nxt; 14 }e[N]; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 19 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 20 return x*f; 21 } 22 23 void add(int u,int v,int w) 24 { 25 e[++e_cnt].v=v; 26 e[e_cnt].w=w; 27 e[e_cnt].nxt=head[u]; 28 head[u]=e_cnt; 29 } 30 31 int main() 32 { 33 n=read(); 34 m=read(); 35 k=read(); 36 for (int i=1;i<=m;i++) 37 { 38 int u=read(); 39 int v=read(); 40 int w=read(); 41 add(u,v,w); 42 add(v,u,w); 43 } 44 for (int i=1;i<=k;i++) 45 vis[read()]=true; 46 int ans=INF; 47 for (int i=1;i<=n;i++) 48 if(vis[i]) 49 for (int j=head[i];j;j=e[j].nxt) 50 if(!vis[e[j].v]) 51 ans=min(ans,e[j].w); 52 if(ans==INF) 53 cout<<-1; 54 else 55 cout<<ans; 56 return 0; 57 //Amireux_35 58 }
1 // Problem: CF1242B 0-1 MST 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1242B 4 // Memory Limit: 250 MB 5 // Time Limit: 1000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define ll long long 14 const int N = 1e6+5; 15 int n,m,id,cnt,ans=-1,e_cnt,Min,p[N],fa[N],siz[N],head[N]; 16 struct edge{ 17 int v; 18 int nxt; 19 }e[4*N]; 20 bool vis[N],k[N]; 21 inline int read() 22 { 23 int x=0,f=1;char ch=getchar(); 24 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 25 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 26 return x*f; 27 } 28 29 void add(int u,int v) 30 { 31 e[++e_cnt].v=v; 32 e[e_cnt].nxt=head[u]; 33 head[u]=e_cnt; 34 } 35 36 int Find(int x) 37 { 38 if(fa[x]==x) 39 return x; 40 return fa[x]=Find(fa[x]); 41 } 42 43 void U(int x,int y) 44 { 45 int r1=Find(x); 46 int r2=Find(y); 47 if(r1!=r2) 48 fa[r2]=r1; 49 } 50 51 int main() 52 { 53 n=read(); 54 m=read(); 55 for (int i=1;i<=m;i++) 56 { 57 int u=read(); 58 int v=read(); 59 add(u,v); 60 add(v,u); 61 siz[u]++; 62 siz[v]++; 63 } 64 Min=n; 65 for (int i=1;i<=n;i++) 66 { 67 if(Min>siz[i]) 68 { 69 Min=siz[i]; 70 id=i; 71 } 72 } 73 for (int i=1;i<=n;i++) 74 fa[i]=i; 75 for (int i=head[id];i;i=e[i].nxt) 76 vis[e[i].v]=true; 77 for (int i=1;i<=n;i++) 78 { 79 if(!vis[i]) 80 { 81 fa[i]=id; 82 k[i]=1; 83 } 84 } 85 for (int i=1;i<=n;i++) 86 if(!k[i]) 87 p[++cnt]=i; 88 clear(vis); 89 for (int i=1;i<=n;i++) 90 { 91 int tot=0; 92 for (int j=head[i];j;j=e[j].nxt) 93 { 94 int v=e[j].v; 95 vis[v]=true; 96 tot+=k[v]; 97 } 98 if(tot+cnt<n) 99 U(i,id); 100 for (int j=1;j<=cnt;j++) 101 if(!vis[p[j]]) 102 U(i,p[j]); 103 for (int j=head[i];j;j=e[j].nxt) 104 vis[e[j].v]=0; 105 } 106 for (int i=1;i<=n;i++) 107 if(i==fa[i]) 108 ans++; 109 cout<<ans; 110 return 0; 111 //Amireux_35 112 }
1 // Problem: D. Lazy Student 2 // Contest: Codeforces - Codeforces Round 335 (Div. 2) 3 // URL: https://codeforces.com/problemset/problem/606/D 4 // Memory Limit: 256 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define ll long long 14 const int N = 1e6+5; 15 int n,m,u=2,v=3,cnt=1; 16 bool flag; 17 struct node{ 18 int u; 19 int v; 20 int w; 21 int op; 22 int id; 23 }e[N]; 24 inline int read() 25 { 26 int x=0,f=1;char ch=getchar(); 27 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 28 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 29 return x*f; 30 } 31 32 bool cmp(node a,node b) 33 { 34 if(a.w==b.w) 35 return a.op>b.op; 36 return a.w<b.w; 37 } 38 39 bool out(node a,node b) 40 { 41 return a.id<b.id; 42 } 43 44 int main() 45 { 46 n=read(); 47 m=read(); 48 for (int i=1;i<=m;i++) 49 { 50 e[i].w=read(); 51 e[i].op=read(); 52 e[i].id=i; 53 } 54 sort(e+1,e+1+m,cmp); 55 for (int i=1;i<=m;i++) 56 { 57 if(e[i].op) 58 { 59 e[i].u=1; 60 e[i].v=++cnt; 61 } 62 else 63 { 64 if(v>cnt) 65 { 66 flag=true; 67 break; 68 } 69 e[i].u=u++; 70 e[i].v=v; 71 if(u==v) 72 { 73 v++; 74 u=2; 75 } 76 } 77 } 78 if(flag) 79 cout<<-1; 80 else 81 { 82 sort(e+1,e+1+m,out); 83 for (int i=1;i<=m;i++) 84 cout<<e[i].u<<" "<<e[i].v<<"\n"; 85 } 86 return 0; 87 //Amireux_35 88 }
下午:
最短路问题:
1)Floyd
Floyd还有很多用处
比如:找图中最小环,任意两点最短路径数,计算一个图的传递背包(判断两点是否联通)
2)Dijkstra
单元最短路径算法,即求起点 S 到所有点的最短距离,但有一个限制是不能存在负权边
3)SPFA
用于负权边的图求最短路径
两边DJ即可
第一次跑 n 次 DJ,求出所有点间的最短路
建新图后在跑一次 DJ,求出 S 点到 T 点的最短路
注意开 long long ,并且 INF 要设大一点
1 // Problem: CF95C Volleyball 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF95C 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define int long long 14 const int INF = 0x7fffffffffffffff; 15 const int N = 1e6+5; 16 int n,m,s,t,dis[N],dist[N],cost[N]; 17 bool vis[N]; 18 vector<pair<int,int>> g[N],G[N]; 19 inline int read() 20 { 21 int x=0,f=1;char ch=getchar(); 22 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 23 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 24 return x*f; 25 } 26 27 void DJ1(int s) 28 { 29 clear(vis); 30 for (int i=0;i<=n;i++) 31 dis[i]=INF; 32 dis[s]=0; 33 priority_queue<pair<int,int>> q; 34 q.push(make_pair(0,s)); 35 while (!q.empty()) 36 { 37 int u=q.top().second; 38 q.pop(); 39 if(vis[u]) 40 continue; 41 vis[u]=true; 42 for (int i=0;i<g[u].size();i++) 43 { 44 int v=g[u][i].first; 45 if(!vis[v] && dis[v]>g[u][i].second+dis[u]) 46 { 47 dis[v]=g[u][i].second+dis[u]; 48 q.push(make_pair(-dis[v],v)); 49 } 50 } 51 } 52 for (int i=1;i<=n;i++) 53 if(i!=s && dis[i]<=dist[s]) 54 G[s].push_back(make_pair(i,cost[s])); 55 } 56 57 void DJ2(int s) 58 { 59 clear(vis); 60 for (int i=0;i<=n;i++) 61 dis[i]=INF; 62 dis[s]=0; 63 priority_queue<pair<int,int>> q; 64 q.push(make_pair(0,s)); 65 while (!q.empty()) 66 { 67 int u=q.top().second; 68 q.pop(); 69 if(vis[u]) 70 continue; 71 vis[u]=true; 72 for (int i=0;i<G[u].size();i++) 73 { 74 int v=G[u][i].first; 75 if(!vis[v] && dis[v]>G[u][i].second+dis[u]) 76 { 77 dis[v]=G[u][i].second+dis[u]; 78 q.push(make_pair(-dis[v],v)); 79 } 80 } 81 } 82 } 83 84 signed main() 85 { 86 n=read(); 87 m=read(); 88 s=read(); 89 t=read(); 90 for (int i=1;i<=m;i++) 91 { 92 int u=read(); 93 int v=read(); 94 int w=read(); 95 g[u].push_back(make_pair(v,w)); 96 g[v].push_back(make_pair(u,w)); 97 } 98 for (int i=1;i<=n;i++) 99 { 100 dist[i]=read(); 101 cost[i]=read(); 102 } 103 for (int i=1;i<=n;i++) 104 DJ1(i); 105 DJ2(s); 106 if(dis[t]==INF) 107 cout<<-1; 108 else 109 cout<<dis[t]; 110 return 0; 111 //Amireux_35 112 }
次短路问题:
Floyd
每次加边后,Floyd暴力更新所有点对最短路即可
1 // Problem: CF25C Roads in Berland 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF25C 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define ll long long 14 const int N = 310; 15 int n,m,K,mp[N][N]; 16 inline int read() 17 { 18 int x=0,f=1;char ch=getchar(); 19 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 20 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 21 return x*f; 22 } 23 24 int main() 25 { 26 n=read(); 27 for (int i=1;i<=n;i++) 28 { 29 mp[i][i]=0; 30 for (int j=1;j<=n;j++) 31 mp[i][j]=mp[j][i]=read(); 32 } 33 K=read(); 34 for (int i=1;i<=K;i++) 35 { 36 ll ans=0; 37 int a=read(); 38 int b=read(); 39 int c=read(); 40 if(mp[a][b]>c) 41 { 42 mp[a][b]=mp[b][a]=c; 43 for (int i=1;i<=n;i++) 44 { 45 for (int j=1;j<=n;j++) 46 { 47 if(i==j) 48 continue; 49 mp[i][j]=mp[j][i]=min(mp[i][j],mp[i][a]+mp[a][j]); 50 mp[i][j]=mp[j][i]=min(mp[i][j],mp[i][b]+mp[b][j]); 51 } 52 } 53 } 54 for (int i=1;i<=n;i++) 55 for (int j=i+1;j<=n;j++) 56 ans+=mp[i][j]; 57 cout<<ans<<" "; 58 } 59 return 0; 60 //Amireux_35 61 }
有点权有边权,建虚点,连接每个点,边权为每个点的点权
而对于每个城市之间路径的边权,因为要来回两次,可直接 * 2
然后跑DJ即可(因为第一遍写的SPFA貌似被卡了
1 // Problem: CF938D Buy a Ticket 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF938D 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0x3f,sizeof a) 13 #define int long long 14 const int INF = 0x3f3f3f33f3f3f3f; 15 const int N = 4e5+10; 16 int n,m,a[N],dis[N]; 17 bool vis[N]; 18 vector<pair<int,int>> g[N]; 19 inline int read() 20 { 21 int x=0,f=1;char ch=getchar(); 22 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 23 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 24 return x*f; 25 } 26 27 void DJ(int s) 28 { 29 priority_queue<pair<int,int>> q; 30 q.push(make_pair(0,s)); 31 dis[s]=0; 32 while (!q.empty()) 33 { 34 int u=q.top().second; 35 q.pop(); 36 if(vis[u]) 37 continue; 38 vis[u]=true; 39 for (int i=0;i<g[u].size();i++) 40 { 41 int v=g[u][i].first; 42 if(dis[v]>dis[u]+g[u][i].second) 43 { 44 dis[v]=dis[u]+g[u][i].second; 45 q.push(make_pair(-dis[v],v)); 46 } 47 } 48 } 49 } 50 51 signed main() 52 { 53 n=read(); 54 m=read(); 55 for (int i=1;i<=m;i++) 56 { 57 int u=read(); 58 int v=read(); 59 int w=read(); 60 g[u].push_back(make_pair(v,w*2)); 61 g[v].push_back(make_pair(u,w*2)); 62 } 63 for (int i=1;i<=n;i++) 64 { 65 a[i]=read(); 66 g[0].push_back(make_pair(i,a[i])); 67 g[i].push_back(make_pair(0,a[i])); 68 } 69 clear(dis); 70 DJ(0); 71 for (int i=1;i<=n;i++) 72 cout<<dis[i]<<" "; 73 return 0; 74 //Amireux_35 75 }
差分约束:
1 // Problem: CF1450E Capitalism 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1450E 4 // Memory Limit: 250 MB 5 // Time Limit: 1000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define ll long long 14 const int N = 300; 15 int n,m,pos,ans=-1,a[2*N],fa[2*N],mp[N][N]; 16 inline int read() 17 { 18 int x=0,f=1;char ch=getchar(); 19 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 20 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 21 return x*f; 22 } 23 24 int Find(int x) 25 { 26 if(fa[x]==x) 27 return x; 28 return fa[x]=Find(fa[x]); 29 } 30 31 void U(int x,int y) 32 { 33 int r1=Find(x); 34 int r2=Find(y); 35 if(r1!=r2) 36 fa[r2]=r1; 37 } 38 39 void init() 40 { 41 memset(mp,N,sizeof(mp)); 42 for (int i=1;i<=n;i++) 43 mp[i][i]=0; 44 for (int i=1;i<=2*n;i++) 45 fa[i]=i; 46 } 47 48 int main() 49 { 50 n=read(); 51 m=read(); 52 init(); 53 for (int o=1;o<=m;o++) 54 { 55 int i=read(); 56 int j=read(); 57 int b=read(); 58 U(i+n,j); 59 U(i,j+n); 60 if(b==1) 61 { 62 mp[i][j]=1; 63 mp[j][i]=-1; 64 } 65 else 66 mp[i][j]=mp[j][i]=1; 67 } 68 for (int i=1;i<=n;i++) 69 { 70 if(Find(i)==Find(i+n)) 71 { 72 cout<<"NO"; 73 exit(0); 74 } 75 } 76 for (int k=1;k<=n;k++) 77 for (int i=1;i<=n;i++) 78 for (int j=1;j<=n;j++) 79 mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]); 80 for (int i=1;i<=n;i++) 81 { 82 if(mp[i][i]<0) 83 { 84 cout<<"NO"; 85 exit(0); 86 } 87 int Max=-n-1; 88 for (int j=1;j<=n;j++) 89 Max=max(Max,mp[i][j]); 90 if(Max>ans) 91 { 92 ans=Max; 93 pos=i; 94 } 95 } 96 cout<<"YES"<<"\n"; 97 cout<<ans<<"\n"; 98 for (int i=1;i<=n;i++) 99 cout<<mp[pos][i]<<" "; 100 return 0; 101 //Amireux_35 102 }
1 // Problem: CF1131D Gourmet choice 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1131D 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define int long long 14 const int N = 1e6+5; 15 int n,m,cnt,sum,e_cnt,du[N],fa[N],dis[N],head[N]; 16 string s[N]; 17 struct edge{ 18 int v; 19 int nxt; 20 }e[N]; 21 queue<int> q; 22 inline int read() 23 { 24 int x=0,f=1;char ch=getchar(); 25 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 26 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 27 return x*f; 28 } 29 30 void add(int u,int v) 31 { 32 e[++e_cnt].v=v; 33 e[e_cnt].nxt=head[u]; 34 head[u]=e_cnt; 35 } 36 37 int Find(int x) 38 { 39 if(fa[x]==x) 40 return x; 41 return fa[x]=Find(fa[x]); 42 } 43 44 void U(int x,int y) 45 { 46 int r1=Find(x); 47 int r2=Find(y); 48 if(r1!=r2) 49 fa[r1]=r2; 50 } 51 52 void TP() 53 { 54 for (int i=1;i<=n+m;i++) 55 { 56 if(fa[i]==i) 57 { 58 if(!du[i]) 59 { 60 dis[i]=1; 61 q.push(i); 62 } 63 ++sum; 64 } 65 } 66 while (!q.empty()) 67 { 68 int u=q.front(); 69 q.pop(); 70 ++cnt; 71 for (int i=head[u];i;i=e[i].nxt) 72 { 73 int v=e[i].v; 74 dis[v]=max(dis[v],dis[u]+1); 75 du[v]--; 76 if(!du[v]) 77 q.push(v); 78 } 79 } 80 } 81 82 signed main() 83 { 84 n=read(); 85 m=read(); 86 for (int i=1;i<=n+m;i++) 87 fa[i]=i; 88 for (int i=1;i<=n;i++) 89 { 90 cin>>s[i]; 91 s[i]=' '+s[i]; 92 for (int j=1;j<=m;j++) 93 if(s[i][j]=='=') 94 U(i,j+n); 95 } 96 for (int i=1;i<=n;i++) 97 { 98 for (int j=1;j<=m;j++) 99 { 100 if(s[i][j]=='>') 101 { 102 add(Find(j+n),Find(i)); 103 du[Find(i)]++; 104 } 105 else if(s[i][j]=='<') 106 { 107 add(Find(i),Find(j+n)); 108 du[Find(j+n)]++; 109 } 110 } 111 } 112 TP(); 113 if(cnt!=sum) 114 puts("No"); 115 else 116 { 117 puts("Yes"); 118 for (int i=1;i<=n;i++) 119 cout<<dis[Find(i)]<<" "; 120 putchar('\n'); 121 for (int i=n+1;i<=n+m;i++) 122 cout<<dis[Find(i)]<<" "; 123 } 124 return 0; 125 //Amireux_35 126 }
根据题意可知,要求最短路,同时最短路上最大最小边权,建分层图跑最短路即可
1 // Problem: CF1473E Minimum Path 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1473E 4 // Memory Limit: 250 MB 5 // Time Limit: 3000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0x3f,sizeof a) 13 #define int long long 14 const int N = 1e6+5; 15 int n,m,e_cnt,dis[N],head[N]; 16 bool vis[N]; 17 struct edge{ 18 int v; 19 int w; 20 int nxt; 21 }e[N]; 22 vector<pair<int,int>> g[N]; 23 inline int read() 24 { 25 int x=0,f=1;char ch=getchar(); 26 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 27 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 28 return x*f; 29 } 30 31 void add(int u,int v,int w) 32 { 33 g[u].push_back(make_pair(v,w)); 34 } 35 36 void SPFA(int s) 37 { 38 priority_queue<pair<int,int>> q; 39 dis[s]=0; 40 vis[s]=true; 41 q.push(make_pair(0,s)); 42 while (!q.empty()) 43 { 44 int u=q.top().second; 45 q.pop(); 46 vis[u]=false; 47 for (int i=0;i<g[u].size();i++) 48 { 49 int v=g[u][i].first; 50 if(dis[v]>dis[u]+g[u][i].second) 51 { 52 dis[v]=dis[u]+g[u][i].second; 53 if(!vis[v]) 54 { 55 vis[v]=true; 56 q.push(make_pair(-dis[v],v)); 57 } 58 } 59 } 60 } 61 } 62 63 signed main() 64 { 65 n=read(); 66 m=read(); 67 for (int i=1;i<=m;i++) 68 { 69 int u=read(); 70 int v=read(); 71 int w=read(); 72 add(u,v,w); 73 add(v,u,w); 74 add(u+n,v+n,w),add(v+n,u+n,w); 75 add(u+n*2,v+n*2,w),add(v+n*2,u+n*2,w); 76 add(u+n*3,v+n*3,w),add(v+n*3,u+n*3,w); 77 78 add(u,v+n,w*2),add(v,u+n,w*2); 79 add(u,v+n*2,0),add(v,u+n*2,0); 80 add(u+n,v+n*3,0),add(v+n,u+n*3,0); 81 add(u+2*n,v+3*n,2*w),add(v+2*n,u+3*n,2*w); 82 } 83 clear(dis); 84 SPFA(1); 85 for(int i=2;i<=n;i++) 86 cout<<min(dis[i],dis[n*3+i])<<" "; 87 return 0; 88 //Amireux_35 89 }
首先最短路计数
通过题目易得当警局在 1 或 n 点时,每条最短路都会经过一条安全边,所以等同于最短路计数
其他情况下,只有当 1 到警局的最短路和警局到 n 的最短路之和等于 1 到 n 的最短路,才能使最短路径经过安全边,经过的条数为两倍的 1 到警局 最短路条数乘上警局到 n 的最短路条数。
1 // Problem: CF208C Police Station 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF208C 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define int long long 14 const int N = 1e6+5; 15 const int M = 210; 16 int n,m,e_cnt,cnt[N],sum[M][M],dis[M][M],head[N]; 17 bool vis[N]; 18 struct edge{ 19 int v; 20 int w; 21 int nxt; 22 }e[N]; 23 inline int read() 24 { 25 int x=0,f=1;char ch=getchar(); 26 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 27 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 28 return x*f; 29 } 30 31 void add(int u,int v) 32 { 33 e[++e_cnt].v=v; 34 e[e_cnt].nxt=head[u]; 35 head[u]=e_cnt; 36 } 37 38 void BFS(int s) 39 { 40 clear(vis); 41 queue<int> q; 42 vis[s]=true; 43 q.push(s); 44 sum[s][s]=1; 45 while (!q.empty()) 46 { 47 int u=q.front(); 48 q.pop(); 49 for (int i=head[u];i;i=e[i].nxt) 50 { 51 int v=e[i].v; 52 if(!vis[v]) 53 { 54 vis[v]=true; 55 dis[s][v]=dis[s][u]+1; 56 q.push(v); 57 } 58 if(dis[s][v]==dis[s][u]+1) 59 sum[s][v]+=sum[s][u]; 60 } 61 } 62 } 63 64 signed main() 65 { 66 n=read(); 67 m=read(); 68 for (int i=1;i<=m;i++) 69 { 70 int u=read(); 71 int v=read(); 72 add(u,v); 73 add(v,u); 74 } 75 BFS(1); 76 BFS(n); 77 int k=sum[1][n]; 78 for (int i=2;i<n;i++) 79 if(dis[1][i]+dis[n][i]==dis[1][n]) 80 k=max(k,sum[1][i]*sum[n][i]*2); 81 printf("%.12lf",k*1.0/sum[1][n]); 82 return 0; 83 //Amireux_35 84 }
扩展
prufer序列
对于这样一棵树:
初始叶结点最小为 1 号,因此对应的prufer序列先是 2
然后叶结点 4 号对应的prufer序列是 2
依次可得 5 号对应 3,6 号对应 3,3 号对应 2,7 号对应 2;
最后这棵树的prufer序列为 223322
Prüfer 序列 - OI Wiki (oi-wiki.org)
day3:
连通性问题:
有向无环图:
有向无环图是一种特殊的图,其最大意义在于能够拓扑排序。
拓扑排序:
考虑维护一个入度为 0 的点的集合
因为这些点之间没有依赖关系,我们可以将它放在序列的开头,所有依赖关系,我们可以将它放在序列的开头,所有依赖它的点都在它后面
放在开头后删掉它,更新剩余入度为 0 的点,继续这个过程
1 // Problem: CF1572A Book 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1572A 4 // Memory Limit: 250 MB 5 // Time Limit: 1500 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define ll long long 14 const int N = 2e5+5; 15 int T,n,k,ans,e_cnt,du[N],dis[N],head[N]; 16 struct edge{ 17 int v; 18 int nxt; 19 }e[N]; 20 inline int read() 21 { 22 int x=0,f=1;char ch=getchar(); 23 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 24 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 25 return x*f; 26 } 27 28 void add(int u,int v) 29 { 30 e[++e_cnt].v=v; 31 e[e_cnt].nxt=head[u]; 32 head[u]=e_cnt; 33 } 34 35 queue<int> q; 36 void TP() 37 { 38 for (int i=1;i<=n;i++) 39 { 40 if(!du[i]) 41 { 42 q.push(i); 43 dis[i]=1; 44 } 45 } 46 while (!q.empty()) 47 { 48 int u=q.front(); 49 q.pop(); 50 for (int i=head[u];i;i=e[i].nxt) 51 { 52 int v=e[i].v; 53 if(u>v) 54 dis[v]=max(dis[v],dis[u]+1); 55 else 56 dis[v]=max(dis[v],dis[u]); 57 du[v]--; 58 if(!du[v]) 59 q.push(v); 60 } 61 } 62 for (int i=1;i<=n;i++) 63 { 64 if(du[i]!=0) 65 { 66 ans=-1; 67 return ; 68 } 69 ans=max(ans,dis[i]); 70 } 71 } 72 73 void init() 74 { 75 ans=0; 76 e_cnt=0; 77 clear(du); 78 clear(dis); 79 clear(head); 80 } 81 82 int main() 83 { 84 T=read(); 85 while (T--) 86 { 87 n=read(); 88 init(); 89 for (int i=1;i<=n;i++) 90 { 91 k=read(); 92 for (int j=1;j<=k;j++) 93 { 94 int p=read(); 95 add(p,i); 96 du[i]++; 97 } 98 } 99 TP(); 100 cout<<ans<<"\n"; 101 } 102 return 0; 103 //Amireux_35 104 }
1 // Problem: CF510C Fox And Names 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF510C 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define ll long long 14 const int N = 1e6+5; 15 const int M = 110; 16 int n,cnt,e_cnt,du[N],head[N],vis[M][M]; 17 char s[M][M],ans[N]; 18 struct edge{ 19 int v; 20 int nxt; 21 }e[N]; 22 inline int read() 23 { 24 int x=0,f=1;char ch=getchar(); 25 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 26 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 27 return x*f; 28 } 29 30 void add(int u,int v) 31 { 32 e[++e_cnt].v=v; 33 e[e_cnt].nxt=head[u]; 34 head[u]=e_cnt; 35 } 36 37 void TP() 38 { 39 queue<int> q; 40 for (int i=1;i<=26;i++) 41 if(!du[i]) 42 q.push(i); 43 while (!q.empty()) 44 { 45 int u=q.front(); 46 q.pop(); 47 ans[++cnt]=u+'a'-1; 48 for (int i=head[u];i;i=e[i].nxt) 49 { 50 int v=e[i].v; 51 du[v]--; 52 if(!du[v]) 53 q.push(v); 54 } 55 } 56 } 57 58 int main() 59 { 60 n=read(); 61 for (int i=1;i<=n;i++) 62 scanf("%s",s[i]+1); 63 for (int i=1;i<=n;i++) 64 { 65 for (int j=i+1;j<=n;j++) 66 { 67 int len=min(strlen(s[i]+1),strlen(s[j]+1)); 68 bool flag=false; 69 for (int k=1;k<=len;k++) 70 { 71 if(s[i][k]!=s[j][k]) 72 { 73 flag=true; 74 int u=s[i][k]-'a'+1; 75 int v=s[j][k]-'a'+1; 76 if(!vis[u][v]) 77 { 78 add(u,v); 79 vis[u][v]++; 80 du[v]++; 81 } 82 break; 83 } 84 } 85 if(!flag && strlen(s[i]+1)>strlen(s[j]+1)) 86 { 87 puts("Impossible"); 88 exit(0); 89 } 90 } 91 } 92 TP(); 93 if(cnt==26) 94 cout<<ans+1; 95 else 96 puts("Impossible"); 97 return 0; 98 //Amireux_35 99 }
看题目:最大权值最小,容易得出二分答案。
建出图后,若图中有环,答案显然成立,若没有环,则需要判断图中的最长路是否大于等于 k。
1 // Problem: CF1679D Toss a Coin to Your Graph... 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1679D 4 // Memory Limit: 250 MB 5 // Time Limit: 3000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 // #define clear(a) memset(a,0,sizeof a) 13 #define int long long 14 const int N = 1e6+5; 15 int n,m,k,cnt,sum,Max,a[N],u[N],v[N],du[N],dis[N],vis[N]; 16 vector<int> g[N]; 17 inline int read() 18 { 19 int x=0,f=1;char ch=getchar(); 20 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 21 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 22 return x*f; 23 } 24 25 void init() 26 { 27 cnt=0; 28 sum=0; 29 Max=-1; 30 for (int i=1;i<=n;i++) 31 { 32 g[i].clear(); 33 du[i]=0; 34 dis[i]=0; 35 vis[i]=0; 36 } 37 } 38 39 bool check(int x) 40 { 41 init(); 42 for (int i=1;i<=n;i++) 43 if(a[i]<=x) 44 dis[i]=1; 45 for (int i=1;i<=m;i++) 46 { 47 if(a[u[i]]<=x && a[v[i]]<=x) 48 { 49 du[v[i]]++; 50 g[u[i]].push_back(v[i]); 51 vis[u[i]]=vis[v[i]]=1; 52 } 53 } 54 queue<int> q; 55 for (int i=1;i<=n;i++) 56 { 57 if(!du[i] && vis[i]) 58 { 59 dis[i]=1; 60 q.push(i); 61 sum++; 62 } 63 else 64 sum+=vis[i]; 65 } 66 while (!q.empty()) 67 { 68 int u=q.front(); 69 q.pop(); 70 ++cnt; 71 for (int i=0;i<g[u].size();i++) 72 { 73 int v=g[u][i]; 74 du[v]--; 75 dis[v]=max(dis[v],dis[u]+1); 76 if(!du[v]) 77 q.push(v); 78 } 79 } 80 if(cnt!=sum) 81 return true; 82 for (int i=1;i<=n;i++) 83 Max=max(Max,dis[i]); 84 return Max>=k; 85 } 86 87 signed main() 88 { 89 n=read(); 90 m=read(); 91 k=read(); 92 for (int i=1;i<=n;i++) 93 a[i]=read(); 94 for (int i=1;i<=m;i++) 95 { 96 u[i]=read(); 97 v[i]=read(); 98 } 99 int l=1; 100 int r=1e9; 101 while (l<=r) 102 { 103 int mid=(l+r)>>1; 104 if(check(mid)) 105 r=mid-1; 106 else 107 l=mid+1; 108 } 109 if(r==1e9) 110 cout<<-1; 111 else 112 cout<<r+1; 113 return 0; 114 //Amireux_35 115 }
强连通分量:
1 // Problem: CF1220E Tourism 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1220E 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define int long long 14 const int N = 1e6+5; 15 int n,m,k,e_cnt=1,a[N],f[N],g[N],head[N]; 16 bool vis[N]; 17 struct edge{ 18 int v; 19 int nxt; 20 }e[N]; 21 inline int read() 22 { 23 int x=0,f=1;char ch=getchar(); 24 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 25 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 26 return x*f; 27 } 28 29 void add(int u,int v) 30 { 31 e[++e_cnt].v=v; 32 e[e_cnt].nxt=head[u]; 33 head[u]=e_cnt; 34 } 35 36 void DFS(int u,int now) 37 { 38 int sum=0; 39 int sum_=0; 40 bool flag=false; 41 vis[u]=true; 42 for (int i=head[u];i;i=e[i].nxt) 43 { 44 if(i==now) 45 continue; 46 int v=e[i].v; 47 if(vis[v]) 48 flag=true; 49 else 50 { 51 DFS(v,i^1); 52 if(f[v]>=0) 53 { 54 sum+=f[v]; 55 flag=true; 56 sum_=max(sum_,g[v]-f[v]); 57 } 58 else 59 sum_=max(sum_,g[v]); 60 } 61 } 62 if(flag) 63 f[u]=sum+a[u]; 64 else 65 f[u]=-1; 66 g[u]=sum+sum_+a[u]; 67 } 68 69 signed main() 70 { 71 n=read(); 72 m=read(); 73 for (int i=1;i<=n;i++) 74 a[i]=read(); 75 for (int i=1;i<=m;i++) 76 { 77 int u=read(); 78 int v=read(); 79 add(u,v); 80 add(v,u); 81 } 82 k=read(); 83 DFS(k,0); 84 cout<<g[k]; 85 return 0; 86 //Amireux_35 87 }
有桥则一定无解
无桥则一定有解
注意路径输出
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 1e6+5; 7 int n,m,tim,cnt,e_cnt,dfn[N],low[N],head[N]; 8 bool vis[N]; 9 struct node{ 10 int v; 11 int nxt; 12 }e[N]; 13 struct edge{ 14 int u; 15 int v; 16 }; 17 int ansu[N],ansv[N]; 18 inline int read() 19 { 20 int x=0,f=1;char ch=getchar(); 21 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 22 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 23 return x*f; 24 } 25 26 void add(int u,int v) 27 { 28 e[++e_cnt].v=v; 29 e[e_cnt].nxt=head[u]; 30 head[u]=e_cnt; 31 } 32 33 void TJ(int u,int fa) 34 { 35 low[u]=dfn[u]=++tim; 36 vis[u]=true; 37 for (int i=head[u];i;i=e[i].nxt) 38 { 39 int v=e[i].v; 40 if(v==fa) 41 continue; 42 if(!dfn[v]) 43 { 44 TJ(v,u); 45 ansu[++cnt]=u; 46 ansv[cnt]=v; 47 low[u]=min(low[u],low[v]); 48 } 49 else 50 { 51 low[u]=min(low[u],dfn[v]); 52 if(dfn[v]<dfn[u]) 53 { 54 ansu[++cnt]=u; 55 ansv[cnt]=v; 56 } 57 } 58 if(low[v]>dfn[u]) 59 { 60 putchar('0'); 61 exit(0); 62 } 63 } 64 } 65 66 int main() 67 { 68 n=read(); 69 m=read(); 70 for (int i=1;i<=m;i++) 71 { 72 int u=read(); 73 int v=read(); 74 add(u,v); 75 add(v,u); 76 } 77 TJ(1,-1); 78 for (int i=1;i<=cnt;i++) 79 cout<<ansu[i]<<" "<<ansv[i]<<"\n"; 80 return 0; 81 //Amireux_35 82 }
由题目易得,每个连通块只需要建一个检查站即可
所以首先求出强连通分量并缩点,每个强连通分量里的最小点权作为缩点后的点权,然后新的点权之和就是最小费用。
再求出每个强连通分量中点权与最小点权相同的点数,作为缩完后这个点的大小,根据乘法原理,最小花费的方案数就是缩完点后所有点的大小的乘积。
1 // Problem: CF427C Checkposts 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF427C 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define int long long 14 const int MOD = 1000000007; 15 const int N = 1e6+5; 16 int n,m,tim,cnt,tot,ans,ans_=1,e_cnt,a[N],siz[N],st[N],sum[N],num[N],low[N],dfn[N],head[N]; 17 bool vis[N]; 18 struct edge{ 19 int v; 20 int nxt; 21 }e[N]; 22 inline int read() 23 { 24 int x=0,f=1;char ch=getchar(); 25 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 26 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 27 return x*f; 28 } 29 30 void add(int u,int v) 31 { 32 e[++e_cnt].v=v; 33 e[e_cnt].nxt=head[u]; 34 head[u]=e_cnt; 35 } 36 37 void TJ(int u) 38 { 39 low[u]=dfn[u]=++tim; 40 st[++cnt]=u; 41 vis[u]=true; 42 for (int i=head[u];i;i=e[i].nxt) 43 { 44 int v=e[i].v; 45 if(!dfn[v]) 46 { 47 TJ(v); 48 low[u]=min(low[u],low[v]); 49 } 50 else if(vis[v]) 51 low[u]=min(low[u],dfn[v]); 52 } 53 if(dfn[u]==low[u]) 54 { 55 ++tot; 56 int k=st[cnt--]; 57 vis[k]=false; 58 num[k]=tot; 59 sum[tot]=a[k]; 60 while (k!=u) 61 { 62 k=st[cnt--]; 63 vis[k]=false; 64 num[k]=tot; 65 sum[tot]=min(sum[tot],a[k]); 66 } 67 } 68 } 69 70 signed main() 71 { 72 n=read(); 73 for (int i=1;i<=n;i++) 74 a[i]=read(); 75 m=read(); 76 for (int i=1;i<=m;i++) 77 { 78 int u=read(); 79 int v=read(); 80 add(u,v); 81 } 82 for (int i=1;i<=n;i++) 83 if(!dfn[i]) 84 TJ(i); 85 for (int i=1;i<=n;i++) 86 if(a[i]==sum[num[i]]) 87 siz[num[i]]++; 88 for (int i=1;i<=tot;i++) 89 { 90 ans+=sum[i]; 91 ans_=(ans_*siz[i])%MOD; 92 } 93 cout<<ans<<" "<<ans_%MOD; 94 return 0; 95 //Amireux_35 96 }
2-SAT:
1 // Problem: CF1475F Unusual Matrix 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1475F 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define ll long long 13 const int N = 1100; 14 int T,n; 15 char mp1[N][N],mp2[N][N]; 16 bool vis[N]; 17 inline int read() 18 { 19 int x=0,f=1;char ch=getchar(); 20 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 21 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 22 return x*f; 23 } 24 25 int main() 26 { 27 T=read(); 28 while (T--) 29 { 30 bool flag=false; 31 memset(vis,0,sizeof(vis)); 32 n=read(); 33 for (int i=1;i<=n;i++) 34 scanf("%s",mp1[i]+1); 35 for (int i=1;i<=n;i++) 36 { 37 scanf("%s",mp2[i]+1); 38 for (int j=1;j<=n;j++) 39 mp1[i][j]^=mp2[i][j]; 40 } 41 for (int i=1;i<=n;i++) 42 if(mp1[1][i] & 1) 43 vis[i]=true; 44 for (int i=1;i<=n;i++) 45 for (int j=1;j<=n;j++) 46 mp1[i][j]^=vis[j]; 47 for (int i=1;i<=n;i++) 48 { 49 for (int j=2;j<=n;j++) 50 { 51 if(mp1[i][j-1]!=mp1[i][j]) 52 { 53 puts("NO"); 54 flag=true; 55 break; 56 } 57 } 58 if(flag) 59 break; 60 } 61 if(!flag) 62 puts("YES"); 63 } 64 return 0; 65 //Amireux_35 66 }
线段树:
李超线段树
数学:
概率论
导数
同余
day4:
上午:
图论精题:
思路和前面一个题差不多,也是需要建虚点,对边权进行处理,然后跑最小生成树。
1 // Problem: CF1245D Shichikuji and Power Grid 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1245D 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define int long long 13 const int N = 1e6+5; 14 int n,sum,ans,tot,e_cnt,st_cnt,u[N],v[N],x[N],y[N],c[N],k[N],st[N],fa[N]; 15 struct edge{ 16 int u; 17 int v; 18 int w; 19 }e[6*N]; 20 inline int read() 21 { 22 int x=0,f=1;char ch=getchar(); 23 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 24 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 25 return x*f; 26 } 27 28 void add(int u,int v,int w) 29 { 30 e[++e_cnt].u=u; 31 e[e_cnt].v=v; 32 e[e_cnt].w=w; 33 } 34 35 int Find(int x) 36 { 37 if(fa[x]==x) 38 return x; 39 return fa[x]=Find(fa[x]); 40 } 41 42 bool cmp(edge a,edge b) 43 { 44 return a.w<b.w; 45 } 46 47 void Kru() 48 { 49 sort(e+1,e+1+e_cnt,cmp); 50 for (int i=1;i<=e_cnt;i++) 51 { 52 int U=e[i].u; 53 int V=e[i].v; 54 int W=e[i].w; 55 int r1=Find(U); 56 int r2=Find(V); 57 if(r1!=r2) 58 { 59 fa[r1]=r2; 60 sum++; 61 ans+=W; 62 if(!e[i].u) 63 st[++st_cnt]=e[i].v; 64 else 65 { 66 u[++tot]=e[i].u; 67 v[tot]=e[i].v; 68 } 69 } 70 if(sum==n) 71 break; 72 } 73 } 74 75 signed main() 76 { 77 n=read(); 78 for (int i=1;i<=n;i++) 79 fa[i]=i; 80 for (int i=1;i<=n;i++) 81 { 82 x[i]=read(); 83 y[i]=read(); 84 } 85 for (int i=1;i<=n;i++) 86 { 87 c[i]=read(); 88 add(0,i,c[i]); 89 } 90 for (int i=1;i<=n;i++) 91 k[i]=read(); 92 for (int i=1;i<=n;i++) 93 { 94 for (int j=1;j<=n;j++) 95 { 96 int C=(k[i]+k[j])*(abs(x[i]-x[j])+abs(y[i]-y[j])); 97 add(i,j,C); 98 } 99 } 100 Kru(); 101 cout<<ans<<"\n"<<st_cnt<<"\n"; 102 for (int i=1;i<=st_cnt;i++) 103 cout<<st[i]<<" "; 104 putchar('\n'); 105 cout<<tot<<"\n"; 106 for (int i=1;i<=tot;i++) 107 cout<<u[i]<<" "<<v[i]<<"\n"; 108 return 0; 109 //Amireux_35 110 }
1 // Problem: CF1244D Paint the Tree 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF1244D 4 // Memory Limit: 250 MB 5 // Time Limit: 3000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define int long long 13 const int INF = 0x7fffffffffffffff; 14 const int N = 1e6+5; 15 int n,pos,ANS=INF,a[N],b[N],c[N],k[N],du[N],ans[N]; 16 vector<int> e[N]; 17 inline int read() 18 { 19 int x=0,f=1;char ch=getchar(); 20 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 21 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 22 return x*f; 23 } 24 25 void DFS(int now,int fa,int tot,int A,int B) 26 { 27 int v=-1; 28 for (int i=0;i<e[now].size();i++) 29 if(e[now][i]^fa) 30 v=e[now][i]; 31 if(v==-1) 32 { 33 if((A==1 || A==2) && (B==1 || B==2)) 34 { 35 tot+=c[now]; 36 k[now]=3; 37 } 38 if((A==3 || A==2) && (B==3 || B==2)) 39 { 40 tot+=a[now]; 41 k[now]=1; 42 } 43 if((A==1 || A==3) && (B==1 || B==3)) 44 { 45 tot+=b[now]; 46 k[now]=2; 47 } 48 if(tot<ANS) 49 { 50 ANS=tot; 51 for (int i=1;i<=n;i++) 52 ans[i]=k[i]; 53 } 54 return; 55 } 56 if(!A && !B) 57 { 58 k[now]=1; 59 DFS(v,now,tot+a[now],1,0); 60 k[now]=2; 61 DFS(v,now,tot+b[now],2,0); 62 k[now]=3; 63 DFS(v,now,tot+c[now],3,0); 64 } 65 if(A && !B) 66 { 67 if(A==1) 68 { 69 k[now]=2; 70 DFS(v,now,tot+b[now],A,2); 71 k[now]=3; 72 DFS(v,now,tot+c[now],A,3); 73 } 74 if(A==2) 75 { 76 k[now]=1; 77 DFS(v,now,tot+a[now],A,1); 78 k[now]=3; 79 DFS(v,now,tot+c[now],A,3); 80 } 81 if(A==3) 82 { 83 k[now]=2; 84 DFS(v,now,tot+b[now],A,2); 85 k[now]=1; 86 DFS(v,now,tot+a[now],A,1); 87 } 88 } 89 if(A && B) 90 { 91 if((A==1 || A==2) && (B==1 || B==2)) 92 { 93 k[now]=3; 94 DFS(v,now,tot+c[now],B,3); 95 } 96 if((A==3 || A==2) && (B==3 || B==2)) 97 { 98 k[now]=1; 99 DFS(v,now,tot+a[now],B,1); 100 } 101 if((A==1 || A==3) && (B==1 || B==3)) 102 { 103 k[now]=2; 104 DFS(v,now,tot+b[now],B,2); 105 } 106 } 107 } 108 109 signed main() 110 { 111 n=read(); 112 for (int i=1;i<=n;i++) 113 a[i]=read(); 114 for (int i=1;i<=n;i++) 115 b[i]=read(); 116 for (int i=1;i<=n;i++) 117 c[i]=read(); 118 for (int i=1;i<=n-1;i++) 119 { 120 int u=read(); 121 int v=read(); 122 e[u].push_back(v); 123 e[v].push_back(u); 124 du[u]++; 125 du[v]++; 126 } 127 for (int i=1;i<=n;i++) 128 { 129 if(du[i]>2) 130 { 131 cout<<-1; 132 exit(0); 133 } 134 if(du[i]==1) 135 pos=i; 136 } 137 DFS(pos,-1,0,0,0); 138 cout<<ANS<<"\n"; 139 for (int i=1;i<=n;i++) 140 cout<<ans[i]<<" "; 141 return 0; 142 //Amireux_35 143 }
1 // Problem: CF623A Graph and String 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF623A 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define ll long long 13 const int N = 1e6+5; 14 const int M = 510; 15 int n,m,cnt,du[N],fa[N],vis[N],mp[M][M]; 16 inline int read() 17 { 18 int x=0,f=1;char ch=getchar(); 19 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 20 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 21 return x*f; 22 } 23 24 int Find(int x) 25 { 26 if(fa[x]==x) 27 return x; 28 return fa[x]=Find(fa[x]); 29 } 30 31 void U(int x,int y) 32 { 33 int r1=Find(x); 34 int r2=Find(y); 35 if(r1!=r2) 36 fa[r1]=r2; 37 } 38 39 int main() 40 { 41 n=read(); 42 m=read(); 43 for (int i=1;i<=n;i++) 44 { 45 fa[i]=i; 46 mp[i][i]=1; 47 } 48 for (int i=1;i<=m;i++) 49 { 50 int u=read(); 51 int v=read(); 52 mp[u][v]=mp[v][u]=1; 53 du[u]++; 54 du[v]++; 55 } 56 for (int i=1;i<=n;i++) 57 { 58 if(du[i]==n-1) 59 continue; 60 for (int j=1;j<=n;j++) 61 if(du[j]!=n-1) 62 if(mp[i][j]) 63 U(i,j); 64 int k=Find(i); 65 if(!vis[k]) 66 vis[k]=++cnt; 67 } 68 if(cnt>2) 69 { 70 puts("No"); 71 exit(0); 72 } 73 for (int i=1;i<=n;i++) 74 { 75 if(du[i]==n-1) 76 continue; 77 for (int j=1;j<=n;j++) 78 { 79 if(Find(i)==Find(j)) 80 { 81 if(!mp[i][j]) 82 { 83 puts("No"); 84 exit(0); 85 } 86 } 87 } 88 } 89 puts("Yes"); 90 for (int i=1;i<=n;i++) 91 { 92 int k=Find(i); 93 if(du[i]==n-1) 94 putchar('b'); 95 else if(vis[k]==1) 96 putchar('a'); 97 else if(vis[k]==2) 98 putchar('c'); 99 } 100 return 0; 101 //Amireux_35 102 }
1 // Problem: CF580C Kefa and Park 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF580C 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define ll long long 13 const int N = 1e6+5; 14 int n,m,ans,e_cnt,a[N],du[N],head[N]; 15 struct edge{ 16 int v; 17 int nxt; 18 }e[N]; 19 inline int read() 20 { 21 int x=0,f=1;char ch=getchar(); 22 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 23 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 24 return x*f; 25 } 26 27 void add(int u,int v) 28 { 29 e[++e_cnt].v=v; 30 e[e_cnt].nxt=head[u]; 31 head[u]=e_cnt; 32 } 33 34 void DFS(int u,int from,int sum) 35 { 36 if(u!=1 && du[u]==1) 37 { 38 if(sum<=m) 39 ans++; 40 return ; 41 } 42 for (int i=head[u];i;i=e[i].nxt) 43 { 44 int v=e[i].v; 45 if(v==from) 46 continue; 47 if(!a[v]) 48 DFS(v,u,0); 49 else if(sum<m) 50 DFS(v,u,sum+1); 51 } 52 } 53 54 int main() 55 { 56 n=read(); 57 m=read(); 58 for (int i=1;i<=n;i++) 59 a[i]=read(); 60 for (int i=1;i<=n-1;i++) 61 { 62 int u=read(); 63 int v=read(); 64 add(u,v); 65 add(v,u); 66 du[u]++; 67 du[v]++; 68 } 69 DFS(1,0,a[1]); 70 cout<<ans; 71 return 0; 72 //Amireux_35 73 }
1 // Problem: CF489D Unbearable Controversy of Being 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF489D 4 // Memory Limit: 250 MB 5 // Time Limit: 1000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define ll long long 13 const int N = 1e6+5; 14 const int M = 3005; 15 int n,m,ans,mp[M][M]; 16 vector<int> e[N]; 17 inline int read() 18 { 19 int x=0,f=1;char ch=getchar(); 20 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 21 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 22 return x*f; 23 } 24 25 int main() 26 { 27 n=read(); 28 m=read(); 29 for (int i=1;i<=m;i++) 30 { 31 int u=read(); 32 int v=read(); 33 e[u].push_back(v); 34 } 35 for (int i=1;i<=n;i++) 36 for (int j=0;j<e[i].size();j++) 37 for (int k=0;k<e[e[i][j]].size();k++) 38 if(i!=e[e[i][j]][k]) 39 mp[i][e[e[i][j]][k]]++; 40 for (int i=1;i<=n;i++) 41 for (int j=1;j<=n;j++) 42 ans+=mp[i][j]*(mp[i][j]-1)/2; 43 cout<<ans; 44 return 0; 45 //Amireux_35 46 }
1 // Problem: CF776D The Door Problem 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/CF776D 4 // Memory Limit: 250 MB 5 // Time Limit: 2000 ms 6 // 7 // Powered by CP Editor (https://cpeditor.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define ll long long 13 const int N = 1e6+5; 14 int n,m,a[N],fa[N],sum[N],k[3][N]; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 19 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 20 return x*f; 21 } 22 23 int Find(int x) 24 { 25 if(fa[x]==x) 26 return x; 27 return fa[x]=Find(fa[x]); 28 } 29 30 void U(int x,int y) 31 { 32 int r1=Find(x); 33 int r2=Find(y); 34 if(r1!=r2) 35 fa[r1]=r2; 36 } 37 38 int main() 39 { 40 n=read(); 41 m=read(); 42 for (int i=1;i<=n;i++) 43 a[i]=read(); 44 for (int i=1;i<=m;i++) 45 { 46 fa[i]=i; 47 fa[i+m]=i+m; 48 } 49 for (int i=1;i<=m;i++) 50 { 51 int x=read(); 52 while (x--) 53 { 54 int y=read(); 55 k[sum[y]++][y]=i; 56 } 57 } 58 for (int i=1;i<=n;i++) 59 { 60 if(!a[i]) 61 { 62 U(k[0][i],k[1][i]+m); 63 U(k[1][i],k[0][i]+m); 64 } 65 else 66 { 67 U(k[0][i],k[1][i]); 68 U(k[0][i]+m,k[1][i]+m); 69 } 70 } 71 for (int i=1;i<=m;i++) 72 { 73 if(Find(i)==Find(i+m)) 74 { 75 puts("NO"); 76 exit(0); 77 } 78 } 79 puts("YES"); 80 return 0; 81 //Amireux_35 82 }
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 2e6+5; 7 int n,cnt,sum,root,e_cnt,t[N],ans[3],num[N],head[N]; 8 struct node{ 9 int v; 10 int nxt; 11 }e[N]; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 16 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 17 return x*f; 18 } 19 20 void add(int u,int v) 21 { 22 e[++e_cnt].v=v; 23 e[e_cnt].nxt=head[u]; 24 head[u]=e_cnt; 25 } 26 27 void DFS(int u,int from) 28 { 29 num[u]=t[u]; 30 for (int i=head[u];i;i=e[i].nxt) 31 { 32 int v=e[i].v; 33 if(v==from) 34 continue; 35 DFS(v,u); 36 num[u]+=num[v]; 37 } 38 if(num[u]==sum) 39 { 40 ans[++cnt]=u; 41 num[u]=0; 42 } 43 } 44 45 int main() 46 { 47 n=read(); 48 for (int i=1;i<=n;i++) 49 { 50 int a=read(); 51 t[i]=read(); 52 if(a) 53 { 54 add(a,i); 55 add(i,a); 56 } 57 else 58 root=i; 59 sum+=t[i]; 60 } 61 if(sum%3) 62 { 63 cout<<-1; 64 exit(0); 65 } 66 sum/=3; 67 DFS(root,0); 68 if(cnt<=2) 69 cout<<-1; 70 else 71 cout<<ans[1]<<" "<<ans[2]; 72 return 0; 73 //Amireux_35 74 }
线性代数
下午:
NOIP历年真题:
题面非常复杂(简直可以说ex,简化为:给出一个DAG,1 ~ m为源点,出度为零的点是汇点,每个源点流量为1,过程中每个节点的流量均等的流向所有的出路。求每个汇点的流量。
依据题意建图:
但是这题还需要高精,已经忘记高精怎么写了,所以这里用了__int128(不是懒
1 // Problem: P7113 [NOIP2020] 排水系统 2 // Contest: Luogu 3 // URL: https://www.luogu.com.cn/problem/P7113 4 // Memory Limit: 512 MB 5 // Time Limit: 1000 ms 6 // 7 // Powered by CP Edixr (https://cpedixr.org) 8 9 //By:Komorebi_03 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clear(a) memset(a,0,sizeof a) 13 #define ll __int128 14 const int N = 1e6+5; 15 int n,m,sum,e_cnt,d[N],in[N],num[N],head[N]; 16 struct edge{ 17 int v; 18 int nxt; 19 }e[N]; 20 struct node{ 21 ll fz; 22 ll fm; 23 }k[N]; 24 queue<int> q; 25 inline int read() 26 { 27 int x=0,f=1;char ch=getchar(); 28 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 29 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 30 return x*f; 31 } 32 33 void write(ll x) 34 { 35 if(x/10) 36 write(x/10); 37 putchar(x%10+'0'); 38 } 39 40 void add(int u,int v) 41 { 42 e[++e_cnt].v=v; 43 e[e_cnt].nxt=head[u]; 44 head[u]=e_cnt; 45 } 46 47 ll gcd(ll x,ll y) 48 { 49 if(y==0) 50 return x; 51 else 52 return gcd(y,x%y); 53 } 54 55 void yf(int p) 56 { 57 ll tmp=gcd(k[p].fz,k[p].fm); 58 k[p].fz/=tmp; 59 k[p].fm/=tmp; 60 } 61 62 void clac(int x,int now) 63 { 64 ll kkk=k[x].fm*k[now].fm/(gcd(k[x].fm,k[now].fm)); 65 k[x].fz=k[x].fz*(kkk/k[x].fm); 66 k[now].fz=k[now].fz*(kkk/k[now].fm); 67 k[x].fz=k[x].fz+k[now].fz; 68 k[x].fm=k[now].fm=kkk; 69 if(k[x].fz) 70 yf(x); 71 } 72 73 void TP() 74 { 75 while (!q.empty()) 76 { 77 int u=q.front(); 78 bool flag=false; 79 q.pop(); 80 if(d[u]) 81 k[u].fm*=d[u]; 82 if(k[u].fz) 83 yf(u); 84 for (int i=head[u];i;i=e[i].nxt) 85 { 86 flag=true; 87 int v=e[i].v; 88 in[v]--; 89 clac(v,u); 90 if(!in[v]) 91 q.push(v); 92 } 93 if(flag) 94 { 95 k[u].fz=0; 96 k[u].fm=1; 97 } 98 } 99 } 100 101 int main() 102 { 103 n=read(); 104 m=read(); 105 for (int i=1;i<=n;i++) 106 { 107 k[i].fz=0; 108 k[i].fm=1; 109 d[i]=read(); 110 if(!d[i]) 111 num[++sum]=i; 112 for (int j=1;j<=d[i];j++) 113 { 114 int a=read(); 115 add(i,a); 116 in[a]++; 117 } 118 } 119 for (int i=1;i<=n;i++) 120 { 121 if(!in[i]) 122 { 123 k[i].fz=k[i].fm=1; 124 q.push(i); 125 } 126 } 127 TP(); 128 for (int i=1;i<=sum;i++) 129 { 130 yf(num[i]); 131 write(k[num[i]].fz); 132 putchar(' '); 133 write(k[num[i]].fm); 134 putchar('\n'); 135 } 136 return 0; 137 //Amireux_35 138 }
并查集
首先从大到小排序
然后再结合敌人的敌人和自己在一个监狱的规律合并
当查找时发现其中两个罪犯不可避免地碰撞到一起时 只能将其输出并结束
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ll long long 5 const int N = 1e6+5; 6 int n,m,fa[N],vis[N]; 7 struct node{ 8 int u; 9 int v; 10 int w; 11 }a[N]; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 16 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 17 return x*f; 18 } 19 20 bool cmp(node x,node y) 21 { 22 return x.w>y.w; 23 } 24 25 int Find(int x) 26 { 27 if(fa[x]==x) 28 return x; 29 return fa[x]=Find(fa[x]); 30 } 31 32 void U(int x,int y) 33 { 34 int s1=Find(x); 35 int s2=Find(y); 36 if(s1!=s2) 37 fa[s1]=s2; 38 } 39 40 bool check(int x,int y) 41 { 42 int t1=Find(x); 43 int t2=Find(y); 44 if(t1==t2) 45 return true; 46 return false; 47 } 48 49 int main() 50 { 51 n=read(); 52 m=read(); 53 for (int i=1;i<=n;i++) 54 fa[i]=i; 55 for (int i=1;i<=m;i++) 56 { 57 a[i].u=read(); 58 a[i].v=read(); 59 a[i].w=read(); 60 } 61 sort(a+1,a+1+m,cmp); 62 for (int i=1;i<=m;i++) 63 { 64 int u=a[i].u; 65 int v=a[i].v; 66 int w=a[i].w; 67 if(check(u,v)) 68 { 69 cout<<w; 70 exit(0); 71 } 72 if(!vis[u]) 73 vis[u]=v; 74 else 75 U(vis[u],v); 76 if(!vis[v]) 77 vis[v]=u; 78 else 79 U(vis[v],u); 80 } 81 cout<<0; 82 return 0; 83 //Amireux_35 84 }
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ll long long 5 const int N = 1e6; 6 const int M = 1e3+5; 7 int n,m,ans,e_cnt,a[N],k[N],in[N],head[N],vis[M][M]; 8 struct node{ 9 int v; 10 int nxt; 11 }e[N]; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 16 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 17 return x*f; 18 } 19 20 void add(int u,int v) 21 { 22 e[++e_cnt].v=v; 23 e[e_cnt].nxt=head[u]; 24 head[u]=e_cnt; 25 } 26 27 void TP() 28 { 29 queue<pair<int,int>> q; 30 for (int i=1;i<=n;i++) 31 if(!in[i]) 32 q.push(make_pair(i,1)); 33 while (!q.empty()) 34 { 35 int now=q.front().first; 36 int dep=q.front().second; 37 q.pop(); 38 if(dep>ans) 39 ans=dep; 40 for (int i=head[now];i;i=e[i].nxt) 41 { 42 int v=e[i].v; 43 in[v]--; 44 if(in[v]==0) 45 q.push(make_pair(v,dep+1)); 46 } 47 } 48 } 49 50 int main() 51 { 52 n=read(); 53 m=read(); 54 while (m--) 55 { 56 memset(k,0,sizeof(k)); 57 int s=read(); 58 for (int i=1;i<=s;i++) 59 { 60 scanf("%d",a+i); 61 k[a[i]]=1; 62 } 63 for (int i=a[1];i<=a[s];i++) 64 { 65 if(!k[i]) 66 { 67 for (int j=1;j<=s;j++) 68 { 69 if(!vis[a[j]][i]) 70 { 71 add(a[j],i); 72 vis[a[j]][i]=1; 73 in[i]++; 74 } 75 } 76 } 77 } 78 } 79 TP(); 80 cout<<ans; 81 return 0; 82 }
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ll long long 5 const int INF = 0x3f3f3f; 6 const int N = 1e6+5; 7 int n,m,s,t,e_cnt,dis[N],head[N]; 8 bool vis[N],vis_[N]; 9 struct edge{ 10 int v; 11 int nxt; 12 }e[N]; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 17 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 18 return x*f; 19 } 20 21 void add(int u,int v) 22 { 23 e[++e_cnt].v=v; 24 e[e_cnt].nxt=head[u]; 25 head[u]=e_cnt; 26 } 27 28 void bfs(int t) 29 { 30 memset(vis,false,sizeof(vis)); 31 queue<int> q; 32 q.push(t); 33 vis[t]=vis_[t]=true; 34 while (!q.empty()) 35 { 36 int u=q.front(); 37 q.pop(); 38 for (int i=head[u];i;i=e[i].nxt) 39 { 40 int v=e[i].v; 41 if(!vis[v]) 42 { 43 vis[v]=true; 44 vis_[v]=true; 45 q.push(v); 46 } 47 } 48 } 49 } 50 51 void SPFA(int t) 52 { 53 memset(vis,false,sizeof(vis)); 54 memset(dis,INF,sizeof(dis)); 55 queue<int> q; 56 q.push(t); 57 vis[t]=true; 58 dis[t]=0; 59 while (!q.empty()) 60 { 61 int u=q.front(); 62 q.pop(); 63 vis[u]=false; 64 for (int i=head[u];i;i=e[i].nxt) 65 { 66 int v=e[i].v; 67 if(dis[v]>dis[u]+1 && vis_[v]) 68 { 69 dis[v]=dis[u]+1; 70 if(!vis[v]) 71 { 72 vis[v]=true; 73 q.push(v); 74 } 75 } 76 } 77 } 78 } 79 80 int main() 81 { 82 n=read(); 83 m=read(); 84 for (int i=1;i<=m;i++) 85 { 86 int u=read(); 87 int v=read(); 88 add(v,u); 89 } 90 s=read(); 91 t=read(); 92 bfs(t); 93 for (int i=1;i<=n;i++) 94 { 95 if(!vis[i]) 96 for (int j=head[i];j;j=e[j].nxt) 97 if(vis_[e[j].v]) 98 vis_[e[j].v]=false; 99 } 100 SPFA(t); 101 if(dis[s]>=INF) 102 cout<<-1; 103 else 104 cout<<dis[s]; 105 return 0; 106 //Amireux_35 107 }
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ll long long 5 const int INF = 0x3f3f3f3f; 6 const int N = 1e6+5; 7 const int M= 1e2; 8 int n,m,cnt,fa[N],vis[N],dep[N],head[N],f[N][M],w[N][M]; 9 struct edge{ 10 int x; 11 int y; 12 int dis; 13 }E[N]; 14 struct node{ 15 int v; 16 int w; 17 int nxt; 18 }e[N]; 19 inline int read() 20 { 21 int x=0,f=1;char ch=getchar(); 22 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 23 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 24 return x*f; 25 } 26 27 void addedge(int u,int v,int w) 28 { 29 e[++cnt].v=v; 30 e[cnt].w=w; 31 e[cnt].nxt=head[u]; 32 head[u]=cnt; 33 } 34 35 bool cmp(edge a,edge b) 36 { 37 return a.dis>b.dis; 38 } 39 40 int Find(int x) 41 { 42 if(fa[x]==x) 43 return x; 44 return fa[x]=Find(fa[x]); 45 } 46 47 void Kru() 48 { 49 sort(E+1,E+1+m,cmp); 50 for (int i=1;i<=n;i++) 51 fa[i]=i; 52 for (int i=1;i<=m;i++) 53 { 54 int s1=Find(E[i].x); 55 int s2=Find(E[i].y); 56 if(s1^s2) 57 { 58 fa[s2]=s1; 59 addedge(E[i].x,E[i].y,E[i].dis); 60 addedge(E[i].y,E[i].x,E[i].dis); 61 } 62 } 63 return ; 64 } 65 66 void dfs(int k) 67 { 68 vis[k]=1; 69 for (int i=head[k];i;i=e[i].nxt) 70 { 71 int v=e[i].v; 72 if(vis[v]) 73 continue; 74 dep[v]=dep[k]+1; 75 f[v][0]=k; 76 w[v][0]=e[i].w; 77 dfs(v); 78 } 79 return ; 80 } 81 82 int LCA(int x,int y) 83 { 84 if(Find(x)^Find(y)) 85 return -1; 86 int ans=INF; 87 if(dep[x]>dep[y]) 88 swap(x,y); 89 for (int i=20;i>=0;i--) 90 { 91 if(dep[f[y][i]]>=dep[x]) 92 { 93 ans=min(ans,w[y][i]); 94 y=f[y][i]; 95 } 96 } 97 if(x==y) 98 return ans; 99 for (int i=20;i>=0;i--) 100 { 101 if(f[x][i]^f[y][i]) 102 { 103 ans=min(ans,min(w[x][i],w[y][i])); 104 x=f[x][i]; 105 y=f[y][i]; 106 } 107 } 108 ans=min(ans,min(w[x][0],w[y][0])); 109 return ans; 110 } 111 112 int main() 113 { 114 n=read(); 115 m=read(); 116 for (int i=1;i<=m;i++) 117 { 118 int x=read(); 119 int y=read(); 120 int z=read(); 121 E[i].x=x; 122 E[i].y=y; 123 E[i].dis=z; 124 } 125 Kru(); 126 for (int i=1;i<=n;i++) 127 { 128 if(!vis[i]) 129 { 130 dep[i]=1; 131 dfs(i); 132 f[i][0]=i; 133 w[i][0]=INF; 134 } 135 } 136 for (int i=1;i<=20;i++) 137 { 138 for (int j=1;j<=n;j++) 139 { 140 f[j][i]=f[f[j][i-1]][i-1]; 141 w[j][i]=min(w[j][i-1],w[f[j][i-1]][i-1]); 142 } 143 } 144 int q=read(); 145 for (int i=1;i<=q;i++) 146 { 147 int x=read(); 148 int y=read(); 149 cout<<LCA(x,y)<<"\n"; 150 } 151 return 0; 152 }
1 //By:Komorebi_03 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define clear(a) memset(a,0,sizeof a) 5 #define ll long long 6 const int N = 1e6+5; 7 int n,Min=0x3f3f3f,t[N],f[N],dis[N]; 8 inline int read() 9 { 10 int x=0,f=1;char ch=getchar(); 11 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 12 while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 13 return x*f; 14 } 15 16 int Find(int x) 17 { 18 if(f[x]!=x) 19 { 20 int root=f[x]; 21 f[x]=Find(f[x]); 22 dis[x]+=dis[root]; 23 } 24 return f[x]; 25 } 26 27 int main() 28 { 29 n=read(); 30 for (int i=1;i<=n;i++) 31 f[i]=i; 32 for (int i=1;i<=n;i++) 33 { 34 t[i]=read(); 35 int r1=Find(i); 36 int r2=Find(t[i]); 37 if(r1!=r2) 38 { 39 f[r1]=r2; 40 dis[i]=dis[t[i]]+1; 41 } 42 else 43 Min=min(Min,dis[i]+dis[t[i]]+1); 44 } 45 cout<<Min; 46 return 0; 47 //Amireux_35 48 }