P3367
标准的并查集题目
都有模板
怎么说呢就是把一堆元素分类存放的思想,然后优化了一下组织内部的头节点问题
#include<bits/stdc++.h>
using namespace std;
int f[100010];
int find(int x)
{
if(f[x]==x)return x;
else return f[x]=find(f[x]);
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)f[i]=i;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
if(a==1)
{
f[find(c)]=find(b);
}
else
{
if(find(b)==find(c))cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
}
return 0;
}
p8604
这个题呢,是在求一个图里除开环上的节点其他所有的节点的个数
怎么说呢,用dfs求出路径总数后,在dfs的路途中每经过一次节点,对这个节点++;
然后判断每个节点是否的经过数是否等于路径数,如果是
那么说明这个节点是在链上的节点
其他的都是在环上()
#include<bits/stdc++.h>
using namespace std;
int n,m;
int start,target;
int vis[1002];
int tem_vis[1002];
int sum;
int maps[1002][1002];
void dfs(int x)
{
if(x==target)
{
sum++;
for(int i=1;i<=n;i++)
if(tem_vis[i]==1)vis[i]++;
}
else
{
for(int i=1;i<=n;i++)
{
if(maps[x][i]==1&&tem_vis[i]==0)
{
tem_vis[i]=1;
dfs(i);
tem_vis[i]=0;
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
maps[a][b]=1;
maps[b][a]=1;
}
cin>>start>>target;
dfs(start);
if(sum>0)
{
int ans=0;
for(int i=1;i<=n;i++)
{
if(vis[i]==sum)ans++;
}
cout<<ans-1;
}
else
cout<<-1;
return 0;
}
p1330
这题的做法是把这个图分层然后用并查集放在同一个父结点上,如果同一层出现了两个节点是连通的,那么不可能输出impossible然后退出程序,可能的话就直接找父节点相同的点的个数,取这两个数的小值就行了
#include<bits/stdc++.h>
using namespace std;
int n,m;
int vis[10005]={0};
int maps[10005][10005]={0};
int father[10005];
int h[10005];
int t[10005]={0};
int finds(int x)
{
if(father[x]==x)return x;
else return father[x]=finds(father[x]);
}
void join(int x,int y)
{
int tem=finds(x);
if(tem!=y)
{
father[y]=tem;
t[tem]+=t[y];
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
father[i]=i;
t[i]=1;
}
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
int x1=finds(a),x2=finds(b);
if(x1==x2)
{
cout<<"Impossible";
exit(0);
}
else
{
if(h[a])join(h[a],x2);
if(h[b])join(h[b],x1);
h[a]=x2;
h[b]=x1;
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
int q=finds(i);
if(!vis[q])
{
int tem=finds(h[i]);
vis[q]=1;
vis[tem]=1;
ans+=min(t[q],t[tem]);
}
}
cout<<ans;
return 0;
}
p3916
嗯很简单,,
反向建邻接表然后直接标记爆搜()
不要问我为什么做了四个小时()
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<vector<int>> maps;
vector<int> arr;
vector<int> vis;
vector<int> anss;
int ans;
int tem=0;
void dfs(int x)
{
if(vis[x])
{
return;
}
anss[x]=tem;
vis[x]=1;
// cout<<x<<endl;
for(int j=0;j<arr[x];j++)
{
dfs(maps[x][j]);
}
}
int main()
{
cin>>n>>m;
maps.resize(n+1,vector<int>(1));
arr.resize(n+1,0);
vis.resize(n+1,0);
anss.resize(n+1,-1);
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
if(a==b)continue;
maps[b][arr[b]]=a;
arr[b]++;
maps[b].resize(arr[b]+1);
}
for(int i=n;i>=1;i--)
{
if(vis[i])continue;
tem=i;
dfs(i);
}
for(int i=1;i<=n;i++)
{
cout<<anss[i]<<" ";
}
return 0;
}
p1119
考察Floyd算法的本质??
如果这题是乱序的话就真的是上难度了,想不到
#include<bits/stdc++.h>
using namespace std;
int n,m;
int times[205];
int maps[201][201];
void floyd(int k)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
maps[i][j]=min(maps[i][k]+maps[k][j],maps[i][j]);
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
maps[i][j]=1e9;
}
}
for(int i=0;i<n;i++)
{
cin>>times[i];
maps[i][i]=0;
}
int start,final,t;
for(int i=0;i<m;i++)
{
cin>>start>>final>>t;
maps[start][final]=maps[final][start]=t;
}
int q;
cin>>q;
int k=0;
for(int i=0;i<q;i++)
{
cin>>start>>final>>t;
while(times[k]<=t&&k<n)
{
floyd(k);
k++;
}
if(times[start]>t||times[final]>t)cout<<-1<<endl;
else
{
if(maps[start][final]==1e9)cout<<-1<<endl;
else
{
cout<<maps[start][final]<<endl;
}
}
}
return 0;
}