开始以为是最小生成树加贪心。。后来发现是判断连通图
tarjan 判断下连通图,建边是无向边,统计连通边数目, 小于 n 直接0
之后缩点,如果全图都强连通 输出 -1;
这题有重复边,开始被卡了一下, 重复边处理很简单, 记录一下和 dfs 时候 pre == to 次数,超过1次肯定就是遇到重复边了,直接更新一下就好了。
当我们发现关键边的时候(边连着的两个点颜色不一致)更新最小值。
别忘了 如果 最小值为 0 要输出 1;
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e6+5;
const int INF=0x3f3f3f3f;
int n,m;
int dfn[maxn],low[maxn],cnt,id[maxn],scc,sum;
struct edge{int to,nxt,v;}ed[maxn];
int head[maxn],tot;
void add(int a,int b,int c)
{
ed[++tot].to = b; ed[tot].v = c; ed[tot].nxt = head[a]; head[a] = tot;
ed[++tot].to = a; ed[tot].v = c; ed[tot].nxt = head[b]; head[b] = tot;
}
int instk[maxn],stk[maxn],top;
void dfs(int s,int p)
{
dfn[s] = low[s] = ++cnt;
stk[++top]=s;
int ct = 0;
for(int i=head[s];i;i=ed[i].nxt)
{
int t = ed[i].to;
if(! dfn[t])
{
sum++; dfs(t, s);
low[s] = min(low[t], low[s]);
}
else if(p==t)
{
if(ct>0)low[s] = min(low[s], dfn[t]);
ct++;
}
else low[s] = min(low[s], dfn[t]);
}
if(dfn[s] == low[s])
{
int x; scc ++;
do{
x = stk[top--];
id[x] = scc;
}while(x != s);
}
}
inline void init()
{
memset(low, 0, sizeof low), cnt = 0;
memset(dfn, 0, sizeof dfn), sum = 1;
memset(head, 0, sizeof head), tot = 0;
memset(id, 0, sizeof id), scc = 0;
memset(stk, 0, sizeof stk), top = 0;
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n&&m)
{
init();
int a,b,c;
for(int i=1;i<=m;i++)
{
cin>>a>>b>>c;
add(a, b, c);
}
dfs(1, 1);int ans = INF;
if(sum < n){puts("0");continue;}
for(int s=1;s<=n;s++)
{
for(int i=head[s];i;i=ed[i].nxt)
{
int t = ed[i].to, v = ed[i].v;
if(id[t] != id[s])
{
ans = min(ans, v);
}
}
}
if(ans == 0){cout<<1<<endl;continue;}
if(ans == INF){cout<<-1<<endl;continue;}
cout<<ans<<endl;
}
return 0;
}