【JZOJ 5435】【NOIP2017提高A组集训10.30】Graph

来源:互联网 发布:法治知识网络大赛登录 编辑:程序博客网 时间:2024/05/23 21:39

Description

这里写图片描述

solution

这不就是LCT板子题嘛

每次暴力找出路径上最早的一条边,记录下来,把那条边断掉,连上这条边;

最后再从开头开始,往后找到第一个位置,使之成为一颗最小生成树,
再把第一条边去掉,继续往后找到记录值为1的边,

复杂度:O(nlog(n))

Code

#include <cstdio>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define efo(i,q) for(int i=A[q],i1=0;i;i1=i,i=B[i][0])#define min(q,w) ((q)>(w)?(w):(q))#define max(q,w) ((q)<(w)?(w):(q))using namespace std;const int N=4500,INF=2147483640;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int m,n,ans;int g[N],b[N],bi[N];struct qqww{    int x,y,v;}a[N];int B[2*N][4],A[N],B0;bool PX(qqww q,qqww w){return q.v<w.v;}int gf(int q){return g[q]==q?q:(g[q]=gf(g[q]));}void link(int q,int w,int e){    B[++B0][0]=A[q];A[q]=B0,B[B0][1]=w,B[B0][2]=e,B[B0][3]=0;    B[++B0][0]=A[w];A[w]=B0,B[B0][1]=q,B[B0][2]=e,B[B0][3]=0;}int mx,OK;void dfs(int q,int fa,int T){    if(q==T){OK=1;return;}    for(;B[A[q]][3];A[q]=B[A[q]][0]);    efo(i,q)if(B[i][3])B[i1][0]=B[i][0],i=i1;        else if(B[i][1]!=fa)        {            dfs(B[i][1],q,T);            if(OK)            {                if(B[mx][2]>B[i][2])mx=i;                return;            }        }}int main(){    freopen("graph.in","r",stdin);    freopen("graph.out","w",stdout);    int q,w,_;    read(_);    B[0][2]=1e9;    while(_--)    {        read(n),read(m);        fo(i,1,m)read(a[i].x),read(a[i].y),read(a[i].v);        sort(a+1,a+1+m,PX);        ans=1e9;B0=1;        fo(i,1,n)g[i]=i,A[i]=0;        q=0;        fo(i,1,m)        {            // printf("%d %d %d\n",i,a[i].x,a[i].y);            int x=gf(a[i].x),y=gf(a[i].y);            if(x!=y)g[x]=y,q++,w=i,b[i]=0;            else            {                mx=OK=0;                dfs(a[i].x,0,a[i].y);                B[mx][3]=1;                B[mx^1][3]=1;                b[i]=B[mx][2];            }            link(a[i].x,a[i].y,i);        }        if(q<n-1){printf("-1\n");continue;}        fo(i,1,n)g[i]=i;        q=0;        fod(i,m,1)        {            int x=gf(a[i].x),y=gf(a[i].y);            if(x!=y)g[x]=y,q++,w=i;            if(q==n-1)break;        }        int j=m+1;bi[j]=1e9;        for(;bi[j];j--,bi[j]=min(b[j],bi[j+1]));        fo(i,1,w)        {            for(;bi[j]<i;j++);            ans=min(ans,a[j-1].v-a[i].v);        }        printf("%d\n",ans);    }    return 0;}
阅读全文
0 0
原创粉丝点击