有向图最小生成树无定根 并要求求出根的位置

Ice_cream’s world II

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5486    Accepted Submission(s): 1389

Problem Description

After awarded lands to ACMers, the queen want to choose a city be her capital. This is an important event in ice_cream world, and it also a very difficult problem, because the world have N cities and M roads, every road was directed. Wiskey is a chief engineer in ice_cream world. The queen asked Wiskey must find a suitable location to establish the capital, beautify the roads which let capital can visit each city and the project’s cost as less as better. If Wiskey can’t fulfill the queen’s require, he will be punishing.

Input

Every case have two integers N and M (N<=1000, M<=10000), the cities numbered 0…N-1, following M lines, each line contain three integers S, T and C, meaning from S to T have a road will cost C.

Output

If no location satisfy the queen’s require, you must be output “impossible”, otherwise, print the minimum cost in this project and suitable city’s number. May be exist many suitable cities, choose the minimum number city. After every case print one blank.

Sample Input

3 1

0 1 1

4 4

0 1 1

0
0 2

10
1 3

20
2 3 30

Sample Output

impossible

40 0

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
const int MAXN = 1e3 + 10;
typedef long long LL;
int id[MAXN] , vis[MAXN] , pre[MAXN] , pos;
LL INF = 1e17 , d[MAXN];
struct node {
    int u , v , cost;
}edge[MAXN * MAXN];

LL zhuliu(int root , int V , int E) {//0,n+1,n+m
    LL res = 0;
    while(true) {
        for(int i = 0 ; i < V ; i++) {
            d[i] = INF;
        }
        for(int i = 0 ; i < E ; i++) {
            int u = edge[i].u , v = edge[i].v;
            if(u != v && d[v] > edge[i].cost) {
                d[v] = edge[i].cost;
                pre[v] = u;
                if(u == root) {
                    pos = i;    //记录位置    除了这里不一样 其他地方都是朱刘算法的模板
                }
            }
        }
        for(int i = 0 ; i < V ; i++) {
            if(d[i] == INF && i != root) {
                return -1;
            }
        }
        int cont = 0;
        memset(id , -1 , sizeof(id));
        memset(vis , -1 , sizeof(vis));
        d[root] = 0;
        for(int i = 0 ; i < V ; i++) {
            int v = i;
            res += d[i];
            while(id[v] == -1 && vis[v] != i && v != root) {
                vis[v] = i;
                v = pre[v];
            }
            if(id[v] == -1 && v != root) {
                for(int u = pre[v] ; u != v ; u = pre[u]) {
                    id[u] = cont;
                }
                id[v] = cont++;
            }
        }
        if(!cont) {
            break;
        }
        for(int i = 0 ; i < V ; i++) {
            if(id[i] == -1) {
                id[i] = cont++;
            }
        }
        for(int i = 0 ; i < E ; i++) {
            int u = edge[i].u , v = edge[i].v;
            edge[i].u = id[u];
            edge[i].v = id[v];
            if(id[u] != id[v]) {
                edge[i].cost -= d[v];
            }
        }
        V = cont;
        root = id[root];
    }
    return res;
}

int main()
{
    int n , m;
    while(~scanf("%d %d" , &n , &m)) {
        LL sum = 0;
        for(int i = 0 ; i < m ; i++) {
            scanf("%d %d %d" , &edge[i].u , &edge[i].v , &edge[i].cost);
            edge[i].u++ , edge[i].v++;
            sum += edge[i].cost;
        }
        sum++;   //边权大于总权值
        for(int i = m ; i < n + m ; i++) {
            edge[i].u = 0;    //0为虚拟节点
            edge[i].v = i - m + 1;
            edge[i].cost = sum;
        }
        LL res = zhuliu(0 , n + 1 , n + m);   //n + 1 个点  n + m 条边
        if(res == -1 || res - sum >= sum) {    //要是res - sum < sum 的话就说明 0的出度为1  说明原图是连通图
            printf("impossible\n\n");
        }
        else {
            printf("%lld %d\n\n" , res - sum , pos - m);
        }
    }
}

时间: 2024-10-05 13:36:47

有向图最小生成树无定根 并要求求出根的位置的相关文章

DIOCP开源项目-高效稳定的服务端解决方案(DIOCP + 无锁队列 + ZeroMQ + QWorkers) 出炉了

[概述] 自从上次发布了[DIOCP开源项目-利用队列+0MQ+多进程逻辑处理,搭建稳定,高效,分布式的服务端]文章后,得到了很多朋友的支持和肯定.这加大了我的开发动力,经过几个晚上的熬夜,终于在昨天晚上,DEMO基本成型,今天再加入了QWorkers来做逻辑处理进程,进一步使得逻辑处理进程更加方便和高效.今天特意写篇blog来记录我的心得与大家分享. [功能实现说明] 沿用上次的草图 目前DEMO图上的功能都已经实现.下面谈谈各部分的实现. 通信服务, 由DIOCP实现,担当与客户端的通信工作

Uva11183-Teen Girl Squad(有向图最小生成树朱刘算法)

解析: 裸的有向图最小生成树 代码 #include<cstdio> #include<cstring> #include<string> #include<iostream> #include<sstream> #include<algorithm> #include<utility> #include<vector> #include<set> #include<map> #incl

root locus 徒手大致绘出根轨迹!一支笔,一张纸,足矣 自动控制原理

徒手绘制根轨迹 可以看出假设的系统传递函数如图中黄色公式部分 特征方程是(s^3+4*s^2+K*s+1) = 0: 绘制根轨迹的方法是 铺垫: 1) 先把所有和K有关的项合并成一大项K(s), (相当于提公因式K) 2)  接着把得到的式子除以不含K的项(如图中蓝色字体部分) 于是可以得到,这是变形后的特征方程 这个方程就变形为1+K * G(s) = 0 的形式了,很重要的铺垫 接着有几条规则需要注意 rule 1 和rule 2 Rule 1 看分子和分母谁的阶次高,把阶次高者的阶次标记为

正则表达式的字符组取反(负值字符集合/范围)^必须出现在起始位置

今天发现[?^a]匹配的匹配的是:?^a,心想^a不是字符组取反吗?难道[?]是新语法? 最后才注意到字符组取反(负值字符集合/范围)的语法规则: 对于字符组取反(负值字符集合/范围),^必须出现在起始位置. 如[^a],意为匹配除a外的所有字符,但若是[#^a],它就不是字符组取反了--而仅仅是一个普通的字符组,意为匹配#^a 在<学习正则表达式>一书中有此规定的表述:

HDU 2121 Ice_cream’s world II(无定根最小树形图)

Ice_cream’s world II Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3115    Accepted Submission(s): 737 Problem Description After awarded lands to ACMers, the queen want to choose a city be her

使用冒泡法进行排序然后用二分查找法找出33的位置 JS

var data = [33, 86, 12, 9, 66, 5, 10, 45, 11, 3]; function sort(data){ var i=0; while(i<data.length-1){ for(var j=0;j<data.length-i-1;j++){ if(data[j]>data[j+1]){ var x=data[j]; data[j]=data[j+1]; data[j+1]=x; } } i++; } } sort(data) BinarySearch

抽象数据类型与C++

类是一种新的数据类型,类似于数据结构,只是它拥有数据结构所没有的部分——“成员函数”,正是因为它所拥有的成员函数这一特性,使得它能隐藏“数据结构”(类)中的数据,不被用户所知道.通过类中的成员函数,使得类的实现与连接都是通过成员函数来进行实现的.接下来我们通过一个实例来对这一概念进行论述: 实例:节流阀类:throttle 对于节流阀,想必大家都比较熟悉,就通过移动控制杆来进行控制液体的流入流出,即为控制流量,所以控制杆所在的位置与通过节流阀的流量便存在一个相关性.通过控制控制杆的位置从而便可以

MATLAB新手教程

MATLAB新手教程   1.MATLAB的基本知识 1-1.基本运算与函数    在MATLAB下进行基本数学运算,仅仅需将运算式直接打入提示号(>>)之後,并按入Enter键就可以.比如: >> (5*2+1.3-0.8)*10/25 ans =4.2000 MATLAB会将运算结果直接存入一变数ans,代表MATLAB运算後的答案(Answer)并显示其数值於萤幕上. 小提示: ">>"是MATLAB的提示符号(Prompt),但在PC中文视窗

Matlab基础

MATLAB入门教程   1.MATLAB的基本知识 1-1.基本运算与函数    在MATLAB下进行基本数学运算,只需将运算式直接打入提示号(>>)之後,并按入Enter键即可.例如: >> (5*2+1.3-0.8)*10/25 ans =4.2000 MATLAB会将运算结果直接存入一变数ans,代表MATLAB运算後的答案(Answer)并显示其数值於萤幕上. 小提示: ">>"是MATLAB的提示符号(Prompt),但在PC中文视窗系统