zoukankan      html  css  js  c++  java
  • [图论最短路]D1T2

    题目描述

    月亮神树的构造非常神奇,它的枝杈交错纵横,树上甚至存在环路,可以视为一个无向带权连通图的结构。月亮神树有一个核心节点,记为 s 。要想消灭月亮神树,必须找到月亮神树的严格最不科学生成树,这是它的弱点,这样就能将其一举摧毁。
    定义:一个图 G 的不科学生成树是 G 的一棵子树,在这棵子树上,从核心节点 s 到任意一个节点 u 的最短路径长度,和在原图上是等长的。其中节点 s 是月亮神树的核心节点。
    定义:一个图 G 的最不科学生成树是 G 的所有不科学生成树中,边权和最小的一棵树。
    定义:一个图 G 的严格最不科学生成树是 G 的所有最不科学生成树中,有序边序列的字典序最小的一棵树。
    定义:一个图 G 的有序边序列是指,将图上所有边按编号从小到大排序后得到的编号序列。当然,子图子树也适用。
    现在给定月亮神树,即给定一个 n 个点 m 条边的无向带权连通图,点的编号从1到n,边的编号从1到m,给定核心节点的编号 s ,求其严格最不科学生成树。

    输入格式

    第一行三个正整数 n,m,s 。
    接下来 m 行,第 i 行三个正整数 u,v,w ,表示编号为 i 的边。
    输入保证图是连通的,保证图上不含重边和自环。。

    输出格式

    第一行两个正整数 cnt 和 sum ,用空格隔开,其中 cnt 表示严格最不科学生成树的边的个数, sum 表示严格最不科学生成树的边权和。
    接下来一行 cnt 个正整数,用空格隔开,为树上所有边的编号,按编号从小到大输出。

    【样例1】
    moontree.in
    3 3 3
    1 2 1
    2 3 1
    1 3 2
    moontree.out
    2 2
    1 2
    【样例2】
    moontree.in
    4 4 4
    2 3 1
    1 2 1
    3 4 1
    4 1 2
    moontree.out
    3 4
    1 3 4
    【数据规模与约定】
    对于25%的数据, 1≤n,m≤10 。
    另有25%的数据, 1≤n,m≤100 。
    对于100%的数据, 1≤n,m≤3*105 ,1≤wi≤109

    题解

    考试中最水的一道,然而我就想骗分,想得贼复杂。
    题目中写到生成树中核心结点到其他点是对应原图中的最短路距离,肯定跟最短路径有些关系。每个点肯定是通过一些最短路上的边加进生成树当中的。并且只会选择一条(不算核心结点)
    首先要生成树边权和最小,则我们取一些权值较小的边替换权值较大的边
    而后要选的边从小到大排的字典序最小,在权值相同的情况下取编号小的即可。
    整个过程通过dij更新时选择即可。
    对,就这。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<ctime>
    #define fi first
    #define se second
    #define N 300005
    using namespace std;
    struct node{
    	int v,ind;
    	long long w;
    	node(){};
    	node (int V,long long W,int I){
    		v = V,w = W,ind = I;
    	}
    	bool operator < (const node &rhs)const {
    		return w > rhs.w;
    	}
    };
    int n,m,s;
    long long sum,dis[N];
    bool vis[N];
    vector<node>G[N];
    pair<int,int>ans[N];
    bool cmp(pair<int,int> a,pair<int,int> b){
    	return a.fi < b.fi;
    }
    void dij(){
    	for (int i = 1;i <= n;i ++)
    		dis[i] = (1ll << 60);
    	priority_queue<node>Q;
    	Q.push(node(s,0,0));
    	dis[s] = 0;
    	while (!Q.empty()){
    		int u = Q.top().v;
    		Q.pop();
    		if (vis[u])
    			continue;
    		vis[u] = 1;
    		for (int i = 0;i < G[u].size();i ++){
    			int v = G[u][i].v,ind = G[u][i].ind;
    			long long w = G[u][i].w;
    			if (dis[v] > dis[u] + w){
    				dis[v] = dis[u] + w;
    				ans[v] = make_pair(ind,w);
    				Q.push(node(v,dis[v],0));
    			}
    			if (dis[v] == dis[u] + w){
    				if (w < ans[v].se)
    					ans[v] = make_pair(ind,w);
    				if (w == ans[v].se && ans[v].fi > ind)
    					ans[v] = make_pair(ind,w);
    			}
    		}
    	}
    }
    int main(){
    	scanf ("%d%d%d",&n,&m,&s);
    	for (int i = 1;i <= m;i ++){
    		int u,v,w;
    		scanf ("%d%d%d",&u,&v,&w);
    		G[u].push_back(node(v,w,i));
    		G[v].push_back(node(u,w,i));
    	}
    	dij();
    	sort (ans + 1,ans + 1 + n,cmp);
    	for (int i = 2;i <= n;i ++)
    		sum += ans[i].se;
    	printf("%d %lld
    ",n - 1,sum);
    	for (int i = 2;i < n;i ++)
    		printf("%d ",ans[i].fi);
    	printf("%d
    ",ans[n].fi);
    }
    
  • 相关阅读:
    python笔记2-python常见数据类型(一)
    python笔记1-环境安装和基本语法
    selenium自动化脚本错误总结
    Postman-Post请求示例
    用PHP删除ftp下载导致的文件空行
    JS实现鼠标悬浮,显示内容
    asp.net中处理程序调用HttpContext.Current.Session获取值出错
    自动化创建tornado项目
    fabric运维
    Python3虚拟环境安装:virtualenv、virtualenvwralpper
  • 原文地址:https://www.cnblogs.com/lover-fucker/p/13566648.html
Copyright © 2011-2022 走看看