这个题感觉会超时的,其实不难想到从大到小进行集合合并,合并的时候判断一下就行了,最开始一直觉得会超时,在想优化的方法,结果~~~想多了
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int inf=1<<29; const int maxn=5050; const int maxm=maxn*maxn/2; struct Edge { int u; int v; int c; bool operator < (const Edge &a)const { return c>a.c; } }E[maxm]; int e,n,m,p[maxn],cnt[maxn],nxt[maxm*2],head[maxn],cost[maxm*2],pnt[maxm*2]; void AddEdge(int u,int v,int c) { pnt[e]=v;nxt[e]=head[u];cost[e]=c;head[u]=e++; pnt[e]=u;nxt[e]=head[v];cost[e]=c;head[v]=e++; } int find(int x) { if(p[x]==-1) return x; return p[x]=find(p[x]); } bool check(int nth) { int mini=inf,maxi=0; for(int u=1;u<=n;u++) if(find(u)==nth) { for(int i=head[u];i!=-1;i=nxt[i]) { if(find(pnt[i])!=nth) maxi=max(maxi,cost[i]); else mini=min(mini,cost[i]); if(mini<=maxi) return false; } } return true; } int main() { int T; scanf("%d",&T); while(T--) { e=0; memset(head,-1,sizeof(head)); memset(p,-1,sizeof(p)); scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) cnt[i]=1; for(int i=0;i<m;i++) { scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].c); AddEdge(E[i].u,E[i].v,E[i].c); } sort(E,E+m); int ans=0; for(int i=0;i<m;i++) { int x=find(E[i].u); int y=find(E[i].v); if(x!=y) { cnt[x]+=cnt[y]; p[y]=x; if(check(x)) ans+=cnt[x]; } } printf("%d\n",ans); } return 0; }