hdu6832(2020hdu多校6t6)

4 篇文章 0 订阅
2 篇文章 0 订阅

题解

所有最短路肯定都出现在最小生成树上。因为克鲁斯卡尔按顺序连边,前面已经连上的肯定最优,所有加起来比当前的还小。
这个我感觉求单源多汇最短路后的剩余图其实和最小生成树其实是一样的。因为如果最小生成树的结论是对的,那么源点到所有点的最短路一定都在树上,剩余图就是这个最小生成树。我试了试都是可以AC的。
开始初始化错了,少初始化了一堆东西,dfs停不下来,MLE。后来wa,因为枚举边端点dp计数没想清。

AC代码

  • dij版本(跑的较慢)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int modd=1e9+7;
const int oo=1e9+10;
const int NN=100100;
const int MM=200100;
int n,m;
int vis[NN],dis[NN];
struct edge{
	int to,cost,from;
}e[MM*2];
vector <int> con[NN];
int a[NN];
struct point{
	int id;
	long long d;
};
struct point_cmp{
	bool operator() (const point &x,const point &y)const{
		if(x.d>y.d)return 1;
		if(x.d==y.d && x.id>y.id)return 1;
		return 0;
	}
};
priority_queue <point ,vector<point> , point_cmp > q;
int pre[NN];
void dij(int origin){
	for(int i=0;i<=n+1;i++)dis[i]=oo;
	dis[origin]=0;
	point st;
	st.id=origin;st.d=0;
	q.push(st);
	while(!q.empty()){
		point root=q.top();
		q.pop();
		if(dis[root.id]!=root.d)continue;
		for(int i=0;i<con[root.id].size();i++){
			edge ed=e[con[root.id][i]];
			int nex=ed.to;
			if(dis[nex]>max(dis[root.id],ed.cost) ){
				pre[nex]=con[root.id][i];
				dis[nex]=max(dis[root.id],ed.cost);
				point neww;
				neww.id=nex;neww.d=dis[nex];
				q.push(neww);
			}
		}
	}
}
long long  siz[NN],sizfa[NN],numson1[NN],numfa1[NN],num1;
int f[MM];
void dfs(int cur,int fa){
	int up=con[cur].size();
	numson1[cur]=(a[cur]==1);
	siz[cur]=1;
	for(int i=0;i<up;i++){
		edge ed=e[con[cur][i]];
		int nex=ed.to;
		if(f[con[cur][i]]&&nex!=fa){
			dfs(nex,cur);
			siz[cur]+=siz[nex];
			numson1[cur]+=numson1[nex];
		}
	}
}
long long ans=0;
long long quan[MM];
void dfsfa(int cur,int fa,int co){
	int up=con[cur].size();
	numfa1[cur]=num1-numson1[cur];
	sizfa[cur]=n-siz[cur];
	if(cur!=1){
		ans+=quan[co]*
		(1ll*numfa1[cur]*(siz[cur]-numson1[cur])%modd+1ll*(sizfa[cur]-numfa1[cur])*numson1[cur]%modd )%modd;
		ans%=modd;
	}
	for(int i=0;i<up;i++){
		edge ed=e[con[cur][i]];
		int nex=ed.to;
		if(f[con[cur][i]]&&nex!=fa){
			dfsfa(nex,cur,ed.cost);
		}
	}
}
int fa[NN];
int getf(int x){
	if(fa[x]==x)return x;
	return (fa[x]=getf(fa[x]));
}
int main(){
	//freopen("1.in","r",stdin);
	quan[0]=1;
	for(int i=1;i<=200000;i++){
		quan[i]=(quan[i-1]<<1)%modd;
	}
	int t;scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		if(n==0)break;
		for(int i=1;i<=n;i++)con[i].clear(),fa[i]=i;
		for(int i=0;i<=m*2;i++)f[i]=0;
		num1=0;
		for(int i=1;i<=n;i++){
			scanf("%d",a+i);
			num1+=(a[i]==1);
		}
		int nume=-1;
		for(int i=1;i<=m;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			e[++nume].to=y;
			e[nume].cost=i;
			e[nume].from=x;
			con[x].push_back(nume);
			e[++nume].to=x;
			e[nume].cost=i;
			e[nume].from=y;
			con[y].push_back(nume);
		}
		dij(1);
		for(int i=1;i<=n;i++){
			// int fx=getf(e[i].from);
			// int fy=getf(e[i].to);
			// if(fx!=fy){
				f[pre[i]]=1;
				f[pre[i]^1]=1;
				//printf("%d %d\n",fx,fy);
			// 	fa[fx]=fy;
			// 	f[i]=1;
			// 	f[i^1]=1;
			// }
		}
		dfs(1,-1);
		ans=0;
		dfsfa(1,-1,0);
		// printf("*%lld %lld %lld\n",sizfa[1],sizfa[2],sizfa[3]);
		// long long ans=0;
		// for(int i=0;i<=nume;i++){
		// 	if(f[i]){
		// 		int fr=e[i].from;
		// 		int to=e[i].to;
		// 		int co=e[i].cost;
		// 		printf("%lld %lld %lld\n",quan[co],numfa1[fr],sizfa[fr]);
		// 		ans=ans+quan[co]*
		// 			(numfa1[fr]*(siz[to]-numson1[to])%modd+(sizfa[fr]-numfa1[fr])*numson1[to]%modd )%modd;
		// 		ans%=modd;
		// 	}
		// }
		printf("%lld\n",ans);
	}
	return 0;
}
/*
6 9
1 1 0 1 0 1 
5 2
5 4
2 1
2 6
2 3
5 3
2 4
4 1
3 4
*/
  • 克鲁斯卡尔版
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int modd=1e9+7;
const int oo=1e9+10;
const int NN=100100;
const int MM=200100;
int n,m;
//int vis[NN],dis[NN];
struct edge{
    int to,cost,from;
}e[MM*2];
vector <int> con[NN];
int a[NN];
// struct point{
//     int id;
//     long long d;
// };
// struct point_cmp{
//     bool operator() (const point &x,const point &y)const{
//         if(x.d>y.d)return 1;
//         if(x.d==y.d && x.id>y.id)return 1;
//         return 0;
//     }
// };
// priority_queue <point ,vector<point> , point_cmp > q;
// int pre[NN];
// void dij(int origin){
//     for(int i=0;i<=n+1;i++)dis[i]=oo;
//     dis[origin]=0;
//     point st;
//     st.id=origin;st.d=0;
//     q.push(st);
//     while(!q.empty()){
//         point root=q.top();
//         q.pop();
//         if(dis[root.id]!=root.d)continue;
//         for(int i=0;i<con[root.id].size();i++){
//             edge ed=e[con[root.id][i]];
//             int nex=ed.to;
//             if(dis[nex]>max(dis[root.id],ed.cost) ){
//                 pre[nex]=con[root.id][i];
//                 dis[nex]=max(dis[root.id],ed.cost);
//                 point neww;
//                 neww.id=nex;neww.d=dis[nex];
//                 q.push(neww);
//             }
//         }
//     }
// }
long long  siz[NN],sizfa[NN],numson1[NN],numfa1[NN],num1;
int f[MM];
void dfs(int cur,int fa){
    int up=con[cur].size();
    numson1[cur]=(a[cur]==1);
    siz[cur]=1;
    for(int i=0;i<up;i++){
        edge ed=e[con[cur][i]];
        int nex=ed.to;
        if(f[con[cur][i]]&&nex!=fa){
            dfs(nex,cur);
            siz[cur]+=siz[nex];
            numson1[cur]+=numson1[nex];
        }
    }
}
long long ans=0;
long long quan[MM];
void dfsfa(int cur,int fa,int co){
    int up=con[cur].size();
    numfa1[cur]=num1-numson1[cur];
    sizfa[cur]=n-siz[cur];
    if(cur!=1){
        ans+=quan[co]*
        (1ll*numfa1[cur]*(siz[cur]-numson1[cur])%modd+1ll*(sizfa[cur]-numfa1[cur])*numson1[cur]%modd )%modd;
        ans%=modd;
    }
    for(int i=0;i<up;i++){
        edge ed=e[con[cur][i]];
        int nex=ed.to;
        if(f[con[cur][i]]&&nex!=fa){
            dfsfa(nex,cur,ed.cost);
        }
    }
}
int fa[NN];
int getf(int x){
    if(fa[x]==x)return x;
    return (fa[x]=getf(fa[x]));
}
int main(){
    //freopen("1.in","r",stdin);
    quan[0]=1;
    for(int i=1;i<=200000;i++){
        quan[i]=(quan[i-1]<<1)%modd;
    }
    int t;scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        if(n==0)break;
        for(int i=1;i<=n;i++)con[i].clear(),fa[i]=i;
        for(int i=0;i<=m*2;i++)f[i]=0;
        num1=0;
        for(int i=1;i<=n;i++){
            scanf("%d",a+i);
            num1+=(a[i]==1);
        }
        int nume=-1;
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            e[++nume].to=y;
            e[nume].cost=i;
            e[nume].from=x;
            con[x].push_back(nume);
            e[++nume].to=x;
            e[nume].cost=i;
            e[nume].from=y;
            con[y].push_back(nume);
        }
        //dij(1);
        for(int i=0;i<=nume;i+=2){
            int fx=getf(e[i].from);
            int fy=getf(e[i].to);
            if(fx!=fy){
                //f[pre[i]]=1;
                //f[pre[i]^1]=1;
                //printf("%d %d\n",fx,fy);
                fa[fx]=fy;
                f[i]=1;
                f[i^1]=1;
            }
        }
        dfs(1,-1);
        ans=0;
        dfsfa(1,-1,0);
        // printf("*%lld %lld %lld\n",sizfa[1],sizfa[2],sizfa[3]);
        // long long ans=0;
        // for(int i=0;i<=nume;i++){
        //     if(f[i]){
        //         int fr=e[i].from;
        //         int to=e[i].to;
        //         int co=e[i].cost;
        //         printf("%lld %lld %lld\n",quan[co],numfa1[fr],sizfa[fr]);
        //         ans=ans+quan[co]*
        //             (numfa1[fr]*(siz[to]-numson1[to])%modd+(sizfa[fr]-numfa1[fr])*numson1[to]%modd )%modd;
        //         ans%=modd;
        //     }
        // }
        printf("%lld\n",ans);
    }
    return 0;
}
/*
6 9
1 1 0 1 0 1 
5 2
5 4
2 1
2 6
2 3
5 3
2 4
4 1
3 4
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值