• 「NOIP2021模拟赛 By ZYQ D」城阙 题解


    「NOIP2021模拟赛 By ZYQ D」城阙

    sol

    其实这道题的建边还很很有思维含量的

    通过分析我们发现,一条边可以走无非两种情况

    • 花费 \(w_i\) 将这条边改成其他颜色

    • 花费 \(sum_{i,c}-w_i\) 将其他同种颜色的边改掉

    但是这样有一种特殊情况无法处理,从x->u->v 是同一种颜色的,但只需要改一条就好了

    所以考虑每个点上都放一些虚点 \(p_{i,c}\)

    对于每个点来说,如果 \(x\) 有一个 \(y\) 与它相连,那么建两条边\((x,p_{y,c},0,0)(p_{y,c},x,sum_{x,c}-w_{x->y})\) 表示格一个建立起联系

    然后刷一次最短路就好了

    code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL INF=0x3f3f3f3f3f3f3f3f;
    const int maxn=3e5+5,maxe=16e5+5,maxm=2e5+5;
    int N,M;
    int lnk[maxn],son[maxe],nxt[maxe],cnt,w[maxe],col[maxe];
    int tot,sum[maxm],num[maxm],rt[maxm];
    int vis[maxn],Q[maxn];
    LL dis[maxn];
    inline void add_e(int x,int y,int c_,int w_){
    	son[++cnt]=y;nxt[cnt]=lnk[x];col[cnt]=c_;w[cnt]=w_;lnk[x]=cnt;
    }
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    void spfa(){
    	memset(dis,INF,sizeof dis);
    	dis[1]=0;int til=1,hed=0;Q[til]=1;
    	while(hed!=til){
    		hed=(hed+1)%maxn;vis[Q[hed]]=0;
    		for(int j=lnk[Q[hed]];j;j=nxt[j])
    			if(dis[Q[hed]]+w[j]<dis[son[j]]){ 
    				dis[son[j]]=dis[Q[hed]]+w[j];
    				if(!vis[son[j]]){vis[Q[til=(til+1)%maxn]=son[j]]=1;}
    		}
    	}
    }
    int main(){
    	freopen("D.in","r",stdin);
    	freopen("D.out","w",stdout);
    	N=read();M=read();
    	for(int i=1;i<=M;i++){
    		int x=read(),y=read(),c_=read(),w_=read();
    		add_e(x,y,c_,w_);add_e(y,x,c_,w_);
    	}
    	tot=N;
    	for(int i=1;i<=N;i++){
    		for(int j=lnk[i];j;j=nxt[j])if(col[j]){
    			sum[col[j]]+=w[j];num[col[j]]++;
    		}
    		for(int j=lnk[i];j;j=nxt[j])if(col[j]){
    			if(num[col[j]]==1)w[j]=0;
    			else{
    				if(!rt[col[j]]) rt[col[j]]=++tot,add_e(i,tot,0,0);
    				add_e(rt[col[j]],son[j],0,sum[col[j]]-w[j]);
    				add_e(son[j],rt[col[j]],0,0);
    			}
    		}
    		for(int j=lnk[i];j;j=nxt[j]) rt[col[j]]=sum[col[j]]=num[col[j]]=0;
    	}
    	spfa();
    	printf("%lld\n",(dis[N]^INF)?dis[N]:-1);
    	return 0;
    }
    
  • 相关阅读:
    真情感动看上海新闻娱乐频道“百家心”
    Treeview Navigation Web Part for SharePoint with SmartPart v1.0
    轻松玩转Typed DataSet, Part III
    微软Avalon和WinForms的发展蓝图
    Proxy Pattern using C#
    System.Threading.Timer类的TimerCallback 委托
    SmartPart v1.0 for SharePoint [Free Web Part]
    分布式应用架构中的数据传输对象(DTO)
    定制SharePoint Portal Server 2003站点的向导
    Bridge Pattern using C#
  • 原文地址:https://www.cnblogs.com/martian148/p/15568032.html
Copyright © 2020-2023  润新知