• 【2019.9.18】Za


    Za

    Kruskal

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int N=2e5+5,M=5e5+5,inf=0x3f3f3f3f;
    int n,m;
    ll ans=0;
    template<class t>void rd(t &x){
    	x=0;int w=0;char ch=0;
    	while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	x=w?-x:x;
    }
    struct edge{
        int u,v,w;
        bool operator<(const edge&X)const{return w<X.w;}
    }e[M];
    int f[N];
    int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    void kruskal(){
    	for(int i=1;i<=n;++i) f[i]=i;
        for(int i=1,u,v;i<=m;++i)
            if(find(u=e[i].u)!=find(v=e[i].v)) f[f[u]]=f[v],ans+=e[i].w;
    }
    
    int main(){
        rd(n),rd(m);
        for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),e[i]=(edge){u,v,w};
        sort(e+1,e+m+1);
        kruskal();
        printf("%lld",ans);
    	return 0;
    }
    

    prim

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    typedef pair<int,int>pii;
    priority_queue<pii,vector<pii>,greater<pii> >q;
    const int N=2e5+5,M=5e5+5,inf=0x3f3f3f3f;
    int n,m;
    ll ans=0;
    template<class t>void rd(t &x){
    	x=0;int w=0;char ch=0;
    	while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	x=w?-x:x;
    }
    
    int head[N],tot=0;
    struct edge{int v,w,nxt;}e[M<<1];
    void add(int u,int v,int w){
    	e[++tot]=(edge){v,w,head[u]},head[u]=tot;
    }
    
    int dis[N],vis[N];
    void prim(){
    	memset(vis,0,sizeof(vis));
    	memset(dis,inf,sizeof(dis));
    	q.push(make_pair(dis[1]=0,1));
    	while(!q.empty()){
    		int u=q.top().second;q.pop();
    		if(vis[u]) continue;
    		ans+=dis[u],vis[u]=1;
    		for(int i=head[u],v,w;i;i=e[i].nxt)
    		if(!vis[v=e[i].v]&&dis[v]>(w=e[i].w))
    		dis[v]=w,q.push(make_pair(dis[v],v));
    	}
    }
    
    int main(){
        rd(n),rd(m);
        for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
        prim();
        printf("%lld",ans);
    	return 0;
    }
    

    走廊泼水节

    将给定的树增加若干条边使其变为完全图 而该树仍未该图中最小生成树

    因为要保证该树仍未图中最小生成树 所以连的边得为其最小边权+1

    集合(S_x)(S_y)之间一共会增加(|S_x|*|S_Y|-1)条边

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    typedef pair<int,int>pii;
    priority_queue<pii,vector<pii>,greater<pii> >q;
    const int N=6000+5,M=5e5+5,inf=0x3f3f3f3f;
    int n,m,f[N],sz[N];
    ll ans;
    template<class t>void rd(t &x){
    	x=0;int w=0;char ch=0;
    	while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	x=w?-x:x;
    }
    
    struct edge{
    	int u,v,w;
    	bool operator<(const edge&X)const{return w<X.w;}
    }e[N];
    int find(int x){return x==f[x]?f[x]:f[x]=find(f[x]);}
    void kruskal(){
    	for(int i=1;i<=n;++i) f[i]=i,sz[i]=1;
    	for(int i=1,x,y;i<n;++i){
    		if((x=find(e[i].u))==(y=find(e[i].v))) continue;
    		ans+=(ll)(e[i].w+1)*(sz[x]*sz[y]-1);
    		f[x]=y,sz[y]+=sz[x];
    	}
    }
    
    int main(){
    	int T;rd(T);
    	while(T--){
    		rd(n);ans=0;
    		for(int i=1,u,v,w;i<n;++i) rd(u),rd(v),rd(w),e[i]=(edge){u,v,w};
    		sort(e+1,e+n);
    		kruskal();
    		printf("%lld
    ",ans);
    	} 
    	return 0;
    }
    

    POJ1639 Picnic Planning

    给定一张(N)个点(M)条边的无向图 求出其一棵最小生成树满足1号节点的读书不超过给定整数(S)

    CF891C Envy

    CF891C luogu

    ==是看的yyb的

    1. 对于任意权值的边,所有最小生成树中这个权值的边的数量是一定的
    2. 对于任意正确加边方案,加完小于某权值的所有边后图的连通性是一样的

    将所有权值相同的边一起考虑 由2可得它们连出来的结果是固定的

    将连边改为脸连通块

    预处理时将每个小于(w_i)的边先加入 再加入边权为(w_i)的边 若形成环 则这组询问失败

    在每次寻问候要将这次询问所构成的修改还原==

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    typedef pair<int,int>pii;
    const int N=5e5+5,M=5e5+5,inf=0x3f3f3f3f;
    int n,m,s,tt,f[N];
    template<class t>void rd(t &x){
    	x=0;int w=0;char ch=0;
    	while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	x=w?-x:x;
    }
    
    struct edge{
    	int u,v,w,id;
    	bool operator<(const edge&X)const{return w<X.w;}
    }e[N],q[N];
    bool cmp(edge X,edge Y){return X.id<Y.id;}
    int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    
    bool kruskal(){
    	int K;rd(K);
    	for(int i=1,x;i<=K;++i) rd(x),q[i]=e[x];
    	sort(q+1,q+K+1);
    	for(int i=1,j=1;i<=K;i=++j){
    		while(j<K&&q[j+1].w==q[j].w) ++j;
    		for(int k=i;k<=j;++k) f[q[k].u]=q[k].u,f[q[k].v]=q[k].v;
    		for(int k=i;k<=j;++k){
    			if(find(q[k].u)==find(q[k].v)) return 0;
    			f[f[q[k].u]]=f[q[k].v];
    		}
    	}
    	return 1;
    }
    
    
    int main(){
    	freopen("in.txt","r",stdin);
    	rd(n),rd(m);
    	for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),e[i]=(edge){u,v,w,i};
    	for(int i=1;i<=n;++i) f[i]=i;
    	sort(e+1,e+m+1);
    	for(int i=1,j=1;i<=m;i=++j){
    		while(j<m&&e[j+1].w==e[j].w) ++j;
    		for(int k=i;k<=j;++k) e[k].u=find(e[k].u),e[k].v=find(e[k].v);
    		for(int k=i;k<=j;++k)
    		if(find(e[k].u)!=find(e[k].v)) f[f[e[k].u]]=f[e[k].v];
    	}
    	sort(e+1,e+m+1,cmp);
    	rd(m);while(m--) puts(kruskal()?"YES":"NO");
    	return 0;
    }
    

    [JLOI2011]飞行路线

    分层最短路模板?注意要用dijkstra

    ==有组数据是m<k 所以要输出(min(dis[t][i],ans))

    四倍经验==

    #include<bits/stdc++.h>
    using namespace std;
    #define Max(x,y) ((x)>(y)?(x):(y))
    #define Min(x,y) ((x)<(y)?(x):(y))
    #define ll long long
    const int N=10000+10,M=50000+10,inf=0x3f3f3f3f;
    int n,m,K,s,t;
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    int head[N],tot=0;
    struct edge{int v,w,nxt;}e[M<<1];
    void add(int u,int v,int w){
    	e[++tot]=(edge){v,w,head[u]},head[u]=tot;
    }
    
    int dis[N][12];bool vis[N][12];
    struct node{
    	int dis,id,us;
    	bool operator>(const node&X)const{return dis>X.dis;}
    };
    priority_queue<node,vector<node>,greater<node> >q;
    void dij(){
    	memset(dis,inf,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	q.push((node){0,s,0}),dis[s][0]=0;
    	while(!q.empty()){
    		node nw=q.top();q.pop();
    		int u=nw.id,us=nw.us;
    		if(vis[u][us]) continue;
    		vis[u][us]=1;
    		for(int i=head[u],v,w;i;i=e[i].nxt){
    			if(dis[v=e[i].v][us]>dis[u][us]+(w=e[i].w))//不用 
    				q.push((node){dis[v][us]=dis[u][us]+(w=e[i].w),v,us});
    			if(us<K&&dis[v][us+1]>dis[u][us])
    				if(!vis[v][us+1]) q.push((node){dis[v][us+1]=dis[u][us],v,us+1});
    		}
    	}
    }
    
    int main(){
    	freopen("in.txt","r",stdin);
    	rd(n),rd(m),rd(K),rd(s),rd(t),++s,++t;
    	for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),add(++u,++v,w),add(v,u,w);
    	spfa();
    	if(dis[t][K]==inf) return puts("-1"),0;
    	int ans=inf;
    	for(int i=0;i<=K;++i) ans=Min(ans,dis[t][i]);
    	printf("%d",ans);
    	return 0;
    }
    

    [USACO14OPEN]GPS的决斗Dueling GPS's

    luoguP3106 bzoj3538

    hin水? 分别跑三次dijkstra

    #include<bits/stdc++.h>
    using namespace std;
    #define Max(x,y) ((x)>(y)?(x):(y))
    #define Min(x,y) ((x)<(y)?(x):(y))
    #define ll long long
    const int N=10000+10,M=50000+10,inf=0x3f3f3f3f;
    typedef pair<int,int>pii;
    int n,m,K,s,t,w2[M];
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    
    int head[N],tot=0;
    struct edge{int v,w,nxt;}e[M];
    void add(int u,int v,int w){
    	e[++tot]=(edge){v,w,head[u]},head[u]=tot;
    }
    
    int dis[N],nw[M],tg[M];bool vis[N];
    priority_queue<pii,vector<pii>,greater<pii> >q;
    void dij(){
    	memset(nw,0,sizeof(nw));
    	memset(vis,0,sizeof(vis));
    	memset(dis,inf,sizeof(dis));
    	dis[s]=0,q.push(make_pair(0,s));
    	while(!q.empty()){
    		int u=q.top().second;q.pop();
    		if(vis[u]) continue;
    		vis[u]=1;
    		for(int i=head[u],v,w;i;i=e[i].nxt)
    		if(dis[v=e[i].v]>dis[u]+(w=e[i].w)){
    			++tg[nw[v]],nw[v]=i,--tg[i];
    			q.push(make_pair(dis[v]=dis[u]+w,v));
    		}
    	}
    } 
    
    int main(){
    	freopen("in.txt","r",stdin);
    	rd(n),rd(m),s=n;
    	for(int i=1,u,v,w1;i<=m;++i) rd(u),rd(v),rd(w1),rd(w2[i]),add(v,u,w1),tg[i]=2;
    	dij();
    	for(int i=1;i<=m;++i) e[i].w=w2[i];
    	dij();
    	for(int i=1;i<=m;++i) e[i].w=tg[i];
    	dij();
    	printf("%d",dis[1]);
    	return 0;
    }
    

    树网的核

    • 枚举(O(n^3))

      两次bfs求出任一直径 枚举距离不超过(s)的两个点(p,q) 然后从核上每个结点出发去求距离 取其中最小值

    • 枚举+贪心(O(n^2))

      可以知道(p,q)两个点距离越远越好 所以只需在直径上枚举(p)点然后直接算出距离其(s)(q)

    • 二分(O(n log SUM))

      可发现答案具有单调性 二分偏心距的可能的最小值 check是否存在这样一个核

    • 单调队列(O(n))

    咕==

    luoguP2245 星际导航

    复习了一遍货车运输?

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define rg register
    const int N=100000+5,M=500000+5,inf=0x3f3f3f3f,P=19650827;
    int n,m,q;
    int dep[N],p[N][25],w[N][25];
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    struct edg{int u,v,w;}E[M];
    bool cmp(edg a,edg b){return a.w<b.w;}
    
    int head[N],tot=0,ans;
    struct edge{int v,nxt,w;}e[M];
    void add(int u,int v,int w){
        e[++tot]=(edge){v,head[u],w};head[u]=tot;
    }
    int f[N];
    int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    void kruskal(){
        for(int i=1;i<=n;++i) f[i]=i;
        for(int i=1,u,v,cnt=0;i<=m;++i){
            if(find(u=E[i].u)!=find(v=E[i].v)){
                f[f[u]]=f[v],++cnt;
                add(u,v,E[i].w),add(v,u,E[i].w);
                if(cnt==n-1) break;
            }
        }
    }
    
    void dfs(int u){
        for(int i=head[u],v;i;i=e[i].nxt)
            if(!dep[v=e[i].v]) dep[v]=dep[u]+1,p[v][0]=u,w[v][0]=e[i].w,dfs(v);
    }
    void build(){
        for(int i=1;i<=n;++i)
            if(!dep[i]) dep[i]=1,p[i][0]=0,dfs(i);
        dfs(1);
        for(int i=1; i<=20; i++)
            for(int j=1; j<=n; j++)
                p[j][i]=p[p[j][i-1]][i-1],
                w[j][i]=max(w[j][i-1], w[p[j][i-1]][i-1]);
    }
    
    int LCA(int a,int b){
        ans=0;
        if(dep[a]>dep[b]) swap(a,b);
        for(int i=20;i>=0;--i){
            if(dep[p[b][i]]<dep[a]) continue;
            ans=max(ans,w[b][i]);b=p[b][i];
        }
        if(a==b) return ans;
        for(int i=20;i>=0;--i){
            if(p[a][i]==p[b][i]) continue;
            ans=max(ans,max(w[a][i],w[b][i]));
            a=p[a][i],b=p[b][i];
        }
        ans=max(ans,max(w[a][0],w[b][0]));
        return ans;
    }
    
    int main(){
        freopen("in.txt","r",stdin);
        rd(n),rd(m);
        for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),E[i]=(edg){u,v,w};
        sort(E+1,E+m+1,cmp);
    	kruskal(),build();
        rd(q);
        for(int i=1,u,v;i<=q;++i){
            rd(u),rd(v);
            if(find(u)!=find(v)) puts("impossible");
            else printf("%d
    ",LCA(u,v));
        }
        return 0;
    }
    
  • 相关阅读:
    centos6升级内核
    centos7启动盘制作
    sed匹配字符串并将匹配行的后几行注释
    cmd下调用xshell登录linux服务器
    centos清除历史命令
    yum错误Cannot retrieve metalink for repository: epel/x86_6
    ansible-playbook
    jdk升级到1.8
    shell瞎记录
    shell 循环
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11545891.html
Copyright © 2020-2023  润新知