AT3945 [ARC092D] Two Faced Edges
https://www.luogu.com.cn/problem/AT3945
考虑 u − > v u->v u−>v这条边对答案的影响
- 如果图中存在 v − > u v->u v−>u的路径,那么肯定会使答案-1
- 如果删掉这条边后,图中还存在 u − > v u->v u−>v的路径,那么会使答案+1
所以上面两个条件有且仅有一个满足时,联通块数会改变
对于第一种,直接暴力跑即可
对于第二种,可以枚举 u u u,然后把边表正反都跑一遍,看看通过不同的边,可不可以到同一个点(染色处理)
可以参考代码
code:
#include<bits/stdc++.h>
#define N 1005
using namespace std;
struct E {
int u, v;
} e[N * N];
int n, m, ok[N][N], okk[N][N], vis[N], col[N], coll[N];
vector<int> g[N];
void dfs(int u, int s) {
ok[s][u] = 1;
for(int i = 0; i < g[u].size(); i ++) {
int v = g[u][i];
if(!ok[s][v]) dfs(v, s);
}
}
void dfss(int u, int o) {
col[u] = o; vis[u] = 1;
for(int i = 0; i < g[u].size(); i ++) {
int v = g[u][i];
if(!vis[v]) {
dfss(v, o);
}
}
}
void dfsss(int u, int o) {
coll[u] = o; vis[u] = 1;
for(int i = 0; i < g[u].size(); i ++) {
int v = g[u][i];
if(!vis[v]) {
dfsss(v, o);
}
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i ++) {
scanf("%d%d", &e[i].u, &e[i].v);
g[e[i].u].push_back(e[i].v);
}
for(int i = 1; i <= n; i ++) dfs(i, i);
for(int u = 1; u <= n; u ++) {
memset(vis, 0, sizeof vis);
memset(col, 0, sizeof col);
memset(coll, 0, sizeof coll);vis[u] = 1;
for(int i = 0; i < g[u].size(); i ++) {
int v = g[u][i];
if(!vis[v]) dfss(v, v);
}
memset(vis, 0, sizeof vis); vis[u] = 1;
for(int i = g[u].size() - 1; i >= 0; i --) {
int v = g[u][i];
if(!vis[v]) dfsss(v, v);
}
for(int v = 1; v <= n; v ++) if(col[v] != coll[v]) okk[u][v] = 1;
/* if(u == 3) {
for(int i = 1; i <= n; i ++) printf("%d ", col[i]); printf("\n");
for(int i = 1; i <= n; i ++) printf("%d ", coll[i]); printf("\n");
}*/
}
for(int i = 1; i <= m; i ++) {
int u = e[i].u, v = e[i].v;
if(ok[v][u] ^ okk[u][v]) printf("diff\n");
else printf("same\n");
}
return 0;
}