P3367 【模板】并查集
模板题,通过路径压缩解决。
#include <iostream>
using namespace std;
int n,m,a[10005];
int find (int f){
if(a[f]==f){
return f;
}
return a[f]=find(a[f]);
}
int main() {
cin >> n >> m;
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=0;i<m;i++){
int x,y,z;
cin >> z >> x >> y;
if(z==1){
a[find(x)]=find(y);
}else{
if(find(x)==find(y)){
cout << 'Y'<<endl;
}else{
cout << 'N'<<endl;
}
}
}
}
P8604 [蓝桥杯 2013 国 C] 危险系数
计算两点之间的路径数量,同时在通过一个节点时增加其被访问次数,如果访问次数与路径数量相等则该点为关键点。
#include <iostream>
using namespace std;
int map[1050][1050]={0},counts[1050]={0};
bool flags[1050];
int sum=0,ans=0,endU,endV,m,n;
void dfs(int s){
if(s==endV){
sum++;
for(int i=1;i<=n;i++){
if(flags[i]){
counts[i]++;
}
}
return;
}
for(int i=1;i<=n;i++){
if(map[s][i]&&!flags[i]){
flags[i]= true;
dfs(i);
flags[i]= false;
}
}
}
int main() {
cin >> n >> m;
for(int i=1;i<=m;i++){
int u,v;
cin >> u >> v;
map[u][v]=1;
map[v][u]=1;
}
cin >> endU >> endV;
dfs(endU);
for(int i=1;i<=n;i++){
if(counts[i]==sum){
ans++;
}
}
cout << ans-1;
}
P1330 封锁阳光大学
可以理解为对图上的节点染色,相邻点颜色不同,统计两种颜色中数量更少的那一种颜色节点的数量即为河蟹数量,如果相邻节点颜色相同即无法完全封锁。
#include <iostream>
using namespace std;
struct Edge{
int v, next;
}edge[200050];
int head[20050],cnt=0;
bool colored[20050]={0};
int colors[20050]={0};
int sum[2];
void addEdge(int tail,int front){
cnt++;
edge[cnt].v=front;
edge[cnt].next = head[tail];
head[tail]=cnt;
}
bool dfs(int node,int color){
if(colored[node]){
if(colors[node]==color){
return true;
}
return false;
}
colored[node]= true;
colors[node]=color;
sum[color]++;
bool flag=true;
for(int i=head[node];i!=0&&flag;i=edge[i].next){
flag=flag&&dfs(edge[i].v,1-color);
}
return flag;
}
int main(){
int n,m;
cin >> n >> m;
for(int i=0;i<m;i++){
int u,v;
cin >> u >> v;
addEdge(u,v);
addEdge(v,u);
}
int ans=0;
for(int i=1;i<=n;i++){
if(colored[i]){
continue;
}
sum[0]=sum[1]=0;
if(!dfs(i,0)){
cout << "Impossible";
return 0;
}else{
if(sum[0]<sum[1]){
ans+=sum[0];
}else{
ans+=sum[1];
}
}
}
cout << ans;
}
P3916 图的遍历
反向建图后DFS遍历图,从最大的节点开始逐个节点作为DFS起点,遇到的节点都将其end值设置为起点,如果end已经有值则不进行更新。
#include <iostream>
using namespace std;
struct Edge{
int v,next;
}edge[200050];
int head[200050]={0};
int cnt=0;
int endV[200050]={0};
void addEdge(int in,int out){
cnt++;
edge[cnt].v=out;
edge[cnt].next=head[in];
head[in]=cnt;
}
int n,m;
void dfs(int s,int target){
if(endV[s]){return;}
endV[s]=target;
for(int i=head[s];i;i=edge[i].next){
dfs(edge[i].v,target);
}
}
int main() {
cin >> n >> m;
for(int i=0;i<m;i++){
int u,v;
cin >> u >> v;
addEdge(v,u);
}
for(int i=n;i;i--){
dfs(i,i);
}
for(int i=1;i<=n;i++){
cout << endV[i]<<' ';
}
}
P1119 灾后重建
通过Floyd算法解决,但是并不是每一天都使用一次Floyd,由于t不下降,则可以在刚开始的时候,前边每有一个村庄修建完毕,就把他和他之前的所有村庄的Floyd矩阵求出,后方的村庄此时还没有建成,不需要更新。
#include <iostream>
using namespace std;
#define INF 0x3f3f3f3f
int n,m,q;
int map[250][250],t[250];
void Floyd(int k){
for(int i=0;i<n;i++)for(int j=0;j<n;j++){
if(map[i][k]+map[k][j]<map[i][j]){
map[i][j]=map[i][k]+map[k][j];
}
}
}
int main(){
cin >> n >> m;
for(int i=0;i<n;i++)for(int j=0;j<n;j++){
if(i==j){map[i][j]=0;}
else{map[i][j]=INF;}
}
for(int i=0;i<n;i++){
cin >> t[i];
}
for(int i=0;i<m;i++){
int u,v,w;
cin >> u>>v>>w;
map[u][v]=map[v][u]=w;
}
cin >> q;
int index=0;
for(int i=0;i<q;i++){
int x,y,day;
cin >> x >> y >> day;
while(t[index]<=day&&index<n){
Floyd(index);
index++;
}
if(t[x]>day||t[y]>day||map[x][y]>=INF){
cout << -1 << endl;
}else{
cout << map[x][y]<<endl;
}
}
}