有向图缩点targan算法
P3387 【模板】缩点
思路:先用targan缩点,将图转换成拓扑图,再进行dfs
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
const int N=1e4+5;
const int M=1e5+5;
int cnt = 1;
int h[N];
int e[M << 1], nx[M << 1];
int w[N];
int bn[N];
int wn[N];
bool vis[N];
int eg[M][2];
void add(int a, int b) {
e[cnt] = b, nx[cnt] = h[a], h[a] = cnt++;
}
void dfs(int u, int f) {
vis[u] = true;
int mx = 0;
for (int i = h[u]; i; i = nx[i]) {
int t = e[i];
if (!vis[t]) {
dfs(t, u);
}
mx = max(mx, wn[t]);
}
wn[u] += mx;
}
struct targan {
int cnt = 1;
int h[N];
int e[M<<1], nx[M<<1];
int n;
int dfn[N], low[N];
int inStack[N];
stack<int> s;
int t = 0;
int tn = 0;
void init(int n1){
n = n1;
memset(h, 0, sizeof h);
memset(nx, 0, sizeof nx);
memset(dfn,0,sizeof dfn);
memset(low, 0, sizeof low);
memset(inStack, 0 , sizeof inStack);
cnt = 1;
t = 0, tn=0;
}
void add(int a, int b) {
e[cnt] = b, nx[cnt] = h[a], h[a] = cnt++;
}
void tar_gan(int u) {
t++;
dfn[u] = low[u] = t;
s.push(u);
inStack[u] =true;
for (int i = h[u]; i; i = nx[i]) {
int t = e[i];
if (!dfn[t]) {
tar_gan(t);
low[u] = min(low[u], low[t]);
}
else if (inStack[t]) {
low[u] = min(low[u], dfn[t]);
}
}
if (low[u] == dfn[u]) {
tn++;
int node;
do
{
node = s.top();
bn[node] = tn;
wn[tn] += w[node];
s.pop();
inStack[node] = false;
} while (node!=u);
}
}
void solve() {
for (int i = 1; i <= n; i++) {
if (!dfn[i]) {
tar_gan(i);
}
}
}
};
int main() {
int n,m;
cin>>n>>m;
for (int i = 1; i <= n; i++) {
cin>>w[i];
}
int a,b;
targan t;
t.init(n);
for (int i = 0; i < m; i++) {
cin>>a>>b;
t.add(a, b);
eg[i][0] = a, eg[i][1] = b;
}
t.solve();
for (int i = 0; i < m; i++) {
int bna = bn[eg[i][0]], bnb = bn[eg[i][1]];
if (bna != bnb) {
add(bna, bnb);
}
}
int ans=0;
for (int i = 1; i <= t.tn; i++) {
if (!vis[i]) {
dfs(i, -1);
ans=max(ans, wn[i]);
}
}
cout<<ans;
}
无向图中环缩点,使用并查集
Ice_cream’s world I
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e3+5;
const int M = 1e4+5;
int f[N];
int find(int i){
return f[i]==i?i:(f[i] = find(f[i]));
}
int Union(int i,int j){
int fi = find(i), fj = find(j);
if(fi!=fj){
f[fi] = fj;
return 0;
}
return 1;
}
int main() {
int n,m;
//cin>>n>>m;
while(scanf("%d %d",&n,&m) != EOF){
for(int i=0;i<n;i++){
f[i] = i;
}
int ans = 0;
int a,b;
for(int i=0;i<m;i++){
cin>>a>>b;
ans += Union(a, b);
}
cout<<ans<<endl;
}
}