hdu 6041 I Curse Myself 无向图找环+优先队列

I Curse Myself

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Problem Description

There is a connected undirected graph with weights on its edges. It is guaranteed that each edge appears in at most one simple cycle.

Assuming that the weight of a weighted spanning tree is the sum of weights on its edges, define V(k) as the weight of the k-th smallest weighted spanning tree of this graph, however, V(k) would be defined as zero if there did not exist k different weighted spanning trees.

Please calculate (∑k=1Kk⋅V(k))mod232.

Input

The input contains multiple test cases.

For each test case, the first line contains two positive integers n,m (2≤n≤1000,n−1≤m≤2n−3), the number of nodes and the number of edges of this graph.

Each of the next m lines contains three positive integers x,y,z (1≤x,y≤n,1≤z≤106), meaning an edge weighted z between node x and node y. There does not exist multi-edge or self-loop in this graph.

The last line contains a positive integer K (1≤K≤105).

Output

For each test case, output "Case #x: y" in one line (without quotes), where x indicates the case number starting from 1 and y denotes the answer of corresponding case.

Sample Input

4 3
1 2 1
1 3 2
1 4 3
1
3 3
1 2 1
2 3 2
3 1 3
4
6 7
1 2 4
1 3 2
3 5 7
1 5 3
2 4 1
2 6 2
6 4 5
7

Sample Output

Case #1: 6
Case #2: 26
Case #3: 493

Source

2017 Multi-University Training Contest - Team 1

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
#define PI acosI(-1.0)
typedef long long ll;
typedef pair<int,int> P;
const int maxn=1e3+100,maxm=1e5+100,inf=0x3f3f3f3f,mod=1e9+7;
const ll INF=1e13+7;

struct is
{
    int x,r;
    bool operator <(const is &c)const
    {
        return x<c.x;
    }
};
int d[maxn],n,m,k;
inline void update(vector<int>&a,vector<int>&b)
{
    priority_queue<is>q;
    for(int i=0;i<b.size();i++)
        d[i] = 0,q.push((is){a[0]+b[i],i});
    vector<int>ans;
    for(int i=1;i<=k;i++)
    {
        if(q.empty())break;
        is x=q.top();
        q.pop();
        ans.push_back(x.x);
        if(d[x.r]+1<a.size())
            q.push((is){a[++d[x.r]]+b[x.r],x.r});
    }
    a=ans;
}
int cmp(int x,int y)
{
    return x>y;
}
struct edge
{
    int from,to,d,nex;
}G[maxn<<2];
int head[maxn],edg;
inline void addedge(int u,int v,int d)
{
    G[++edg]=(edge){u,v,d,head[u]},head[u]=edg;
    G[++edg]=(edge){v,u,d,head[v]},head[v]=edg;
}
int pre[maxn],bccno[maxn];
int dfs_clock,bcc_cnt;
stack<int>s;
vector<int>ans,fuck;
inline int dfs(int u,int fa)
{
    int lowu=++dfs_clock;
    pre[u]=dfs_clock;
    int child=0;
    for(int i=head[u]; i!=-1; i=G[i].nex)
    {
        int v=G[i].to;
        edge e=G[i];
        if(!pre[v])
        {
            s.push(i);
            child++;
            int lowv=dfs(v,u);
            lowu=min(lowu,lowv);
            if(lowv>=pre[u])
            {
                bcc_cnt++;
                fuck.clear();
                while(true)
                {
                    int e=s.top();
                    s.pop();
                    fuck.push_back(G[e].d);
                    if(bccno[G[e].from]!=bcc_cnt)
                        bccno[G[e].from]=bcc_cnt;
                    if(bccno[G[e].to]!=bcc_cnt)
                        bccno[G[e].to]=bcc_cnt;
                    if(G[e].from==u&&G[e].to==v) break;
                }
                if(fuck.size()>1)update(ans,fuck);
            }
        }
        else if(pre[v]<pre[u]&&v!=fa)
        {
            s.push(i);
            lowu=min(lowu,pre[v]);
        }
    }
    return lowu;
}
void init()
{
    dfs_clock=bcc_cnt=edg=0;
    for(int i=0;i<=n;i++)
        head[i]=-1,bccno[i]=0,pre[i]=0;
    ans.clear();
    ans.push_back(0);
}

int main()
{
    int cas=1;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        ll sumsum=0;
        for(int i=1; i<=m; i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            sumsum+=z;
            addedge(x,y,z);
        }
        scanf("%d",&k);
        dfs(1,-1);
        ll out=0,MOD=(1LL<<32);
        printf("Case #%d: ",cas++);

        for(int i=1;i<=k;i++)
        {
            if(i-1>=ans.size())break;
            out+=1LL*(sumsum-ans[i-1])*i;
            out%=MOD;
        }
        printf("%lld\n",out);
    }
    return 0;
}
时间: 2024-10-12 15:11:38

hdu 6041 I Curse Myself 无向图找环+优先队列的相关文章

zstu.4191: 无向图找环(dfs树 + 邻接表)

4191: 无向图找环 Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 117  Solved: 34 Description 给你一副无向图,每条边有边权,保证图联通,现在让你判断这个图是否有异或值大于零的环存在. Input 多组测试数据,每组先输入两个数n m,表示图的点跟边的数量. 然后是m行,每行三个数a b c.代表一条边的起点,终点,边权. 1 <= n<= 100000, 1 <= m <= 200000. 1 <

HDU 6041 I Curse Myself(二分+搜索)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6041 [题目大意] 给出一个仙人掌图,求第k小生成树 [题解] 首先找到仙人掌图上的环,现在的问题就是从每个环中删除一个元素, 求出删除元素总和中的第K大,我们发现通过限定第K大的大小,可以有效地搜索剪枝, 限制的大小导致搜索出来的总和数量是具有单调性的,我们可以二分这个值, 然后用搜索来定位第K大的大小.Thanks to Claris. [代码] #include <cstdio> #in

zstu校赛4191——DFS——无向图找环

Description 给你一副无向图,每条边有边权,保证图联通,现在让你判断这个图是否有异或值大于零的环存在. Input 多组测试数据,每组先输入两个数n m,表示图的点跟边的数量. 然后是m行,每行三个数a b c.代表一条边的起点,终点,边权. 1 <= n<= 100000, 1 <= m <= 200000. 1 <= a <= n, 1 <= b <= n, a != b. 0 <= c <= 32767 Output 对于每组数据

CodeForces 510B 无向图找环的两种方法(搜索与并查集)

题目连接:http://codeforces.com/problemset/problem/510/B 解法: dfs 每次把父节点的值记录并传递下去,判断一下新达到节点: (1)没有走过 → 继续搜索: (2)走过&&不是父节点(对于本题步数也要>=4) → 找到环: 并查集 每个节点映射成 i*m+j从起点开始分别把它下面与于右面的节点加进来,如果发现有节点已经在集合中,那么环已经找到了. DFS: #include<cstdio> #include<cstdl

ZSTUOJ 4191 无向图找环(dfs)

中文题 直接dfs下去即可,遇到重复访问的点,判断一下该环三部分异或和是否大于0 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 100005; const int M = 400005; int n, m; struct Edge { int u, v, w; Edge() {} Edge(int u, int v, int

HDU - 6370 Werewolf 2018 Multi-University Training Contest 6 (DFS找环)

求确定身份的人的个数. 只能确定狼的身份,因为只能找到谁说了谎.但一个人是否是民,无法确定. 将人视作点,指认关系视作边,有狼边和民边两种边. 确定狼的方法只有两种: 1. 在一个仅由一条狼边组成的环中,狼边指向的那个点必定是狼. 2. 环外指认铁狼为民的也必定是狼. 所以用原图找环求情况1中的铁狼,反向建图找情况2中的狼. #include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn =1

杭电1272 并查集找环+判断连通

杭电1272 并查集找环+判断连通 E - E Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1272 Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B

HDU 4738 Caocao&#39;s Bridges ——(找桥,求联通块)

题意:给你一个无向图,给你一个炸弹去炸掉一条边,使得整个图不再联通,你需要派人去安置炸弹,且派去的人至少要比这条边上的人多.问至少要派去多少个,如果没法完成,就输出-1. 分析:如果这个图是已经是多个联通块了,那么一个人都不用去,如果不是,那么只要找出这个无向图上的桥并且哨兵数量最少的那座把它炸了就行(输出这条边上的哨兵数量即可).直接tarjan就可以写. 注意点:1.可能有重边,所以用手写邻接表的方式存图:2.如果一座桥上没有哨兵,那么你也得至少派去一个人去安置炸弹(因为炸弹不会自己飞过去啊

HDU 4337 King Arthur&#39;s Knights 找出一条哈密顿回路

n个点m条无向边 输出一条哈密顿回路 #include <cstdio> #include <cstring> #include <iostream> using namespace std; const int N = 155; int n, m; bool mp[N][N]; int S, T, top, Stack[N]; bool vis[N]; void _reverse(int l,int r) { while (l<r) swap(Stack[l++