最近的考试暴露了我图论知识一片空白的事实…
所以现在还是开始填坑吧…
这道题是无向图找桥的模板题
桥的判定条件为 low[to[i]]>dfn[x] l o w [ t o [ i ] ] > d f n [ x ]
因为如果一个点的儿子能到达的最早的点都没有高于自身
那么它到它儿子的边就是桥边
然后有几个需要注意的地方
1.有重边,用邻接矩阵判断边权设为无穷大即可
2.如果桥上没有人也要派一个人带炸弹过去
大概就这些 剩下的用 tarjan t a r j a n 就好了
题目链接
#include
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
using namespace std;
const int maxn = 1e3 + 5;
int to[maxn * maxn], head[maxn], nxt[maxn * maxn], v[maxn * maxn], e;
int mp[maxn][maxn];
int cnt, n, m, dfn[maxn], low[maxn], ans;
void add(int x, int y, int z, bool k = 1) {
to[++ e] = y;
nxt[e] = head[x];
head[x] = e;
v[e] = z;
if(k) add(y, x, z, 0);
}
void dfs(int x, int from) {
dfn[x] = low[x] = ++ cnt;
go(x, i)
if(to[i] != from) {
if(!dfn[to[i]]) {
dfs(to[i], x);
low[x] = min(low[x], low[to[i]]);
if(low[to[i]] > dfn[x])
ans = min(ans, v[i]);
}
else
low[x] = min(low[x], dfn[to[i]]);
}
}
void File() {
freopen("4738.in", "r", stdin);
freopen("4738.out", "w", stdout);
}
void Init() {
int x, y, z;
scanf("%d%d", &n, &m);
cnt = e = 0, ans = INT_MAX;
For(i, 1, n) {
head[i] = dfn[i] = low[i] = 0;
For(j, 1, n)
mp[i][j] = -1;
}
if(n + m == 0) exit(0);
For(i, 1, m) {
scanf("%d%d%d", &x, &y, &z);
if(mp[x][y] == -1) mp[x][y] = mp[y][x] = z;
else mp[x][y] = mp[y][x] = INT_MAX;
}
For(i, 1, n)
For(j, 1, n)
if(mp[i][j] != -1)
add(i, j, mp[i][j]);
}
void Solve() {
dfs(1, 0);
For(i, 1, n)
if(!dfn[i])
return void(printf("%d\n", 0));
if(ans == INT_MAX) printf("-1\n");
else if(ans == 0) printf("1\n");
else printf("%d\n", ans);
}
int main() {
File();
while(true) {
Init();
Solve();
}
return 0;
}