zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:那一天她里我而去(堆优化Dijkstra)

    题目传送门(内部题3)


    输入格式

    每个测试点有多组测试数据。
    第一行有一个正整数T表示数据组数。
    接下来对于每组数据,第一行有两个正整数n,m分别代表图的点数和边数。
    接下来有m行,每行三个整数u,v,d表示u,v之间存在一条长度为d的路径。
    保证不存在重边,自环。


    输出格式

    对于每组测试数据,输出题目中所求的最小环的长度。
    无解输出-1。


    样例

    样例输入

    2
    3 3
    1 2 1
    2 3 1
    3 1 1
    4 5
    1 2 2
    2 3 2
    3 4 2
    1 4 2
    1 3 5

    样例输出

    3
    8


    数据范围与提示

    $T leqslant 10$

    $d leqslant {10}^3$

    对于30%的数据:

    $n leqslant {10}^3$

    $m leqslant 4 imes {10}^3$

    对于另外30%的数据:

    $n leqslant {10}^4$

    $m=n$

    对于100%的数据:

    $n leqslant {10}^4$

    $m leqslant 4 imes {10}^4$


    题解

    这道题要求我们找一个包含节点1的最小环,显然直接dfs求会超时,那么我们试图转化问题。

    将问题转化成:在与节点1直接项链的节点中找一个点,砍掉它与节点一的连边,然后从这个点沿其他路径跑到节点1,再加上砍掉的这个边的权值,在所有的这些情况中找最小的。

    问题就轻松解决了,依次枚举每一个与节点1相连的点即可。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    struct rec
    {
    	int nxt;
    	int to;
    	int w;
    }e[100000];
    int n,m;
    int head[40001],cnt=1;
    int dis[40001];
    bool vis[40001];
    int ans;
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    void pre_work()
    {
    	cnt=1;
    	ans=20020923;
    	memset(head,0,sizeof(head));
    }
    void add(int x,int y,int w)
    {
    	e[++cnt].nxt=head[x];
    	e[cnt].to=y;
    	e[cnt].w=w;
    	head[x]=cnt;
    }
    void Dij(int x)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,0x3f,sizeof(dis));
        q.push(make_pair(0,x));
        dis[x]=0;
        while(!q.empty())
        {
            int flag=q.top().second;
            q.pop();
            if(vis[flag])continue;
            vis[flag]=1;
            for(int i=head[flag];i;i=e[i].nxt)
                if(dis[e[i].to]>dis[flag]+e[i].w)
                {
                    dis[e[i].to]=dis[flag]+e[i].w;
                    q.push(make_pair(dis[e[i].to],e[i].to));
                }
        }
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		pre_work();
    		for(int i=1;i<=m;i++)
    		{
    			int u,v,d;
    			scanf("%d%d%d",&u,&v,&d);
    			add(u,v,d);
    			add(v,u,d);
    		}
    		for(int i=head[1];i;i=e[i].nxt)
    		{
    			int flag=e[i].w;
    			e[i].w=e[i^1].w=20020923;//把这条边赋成极大值就相当于是删掉了这条边
    			Dij(e[i].to);
    			ans=min(ans,dis[1]+flag);
    			e[i].w=e[i^1].w=flag;
    		}
    		if(ans==20020923)puts("-1");
    		else printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    android 推断应用程序是系统程序还是用户程序
    zoj-3792-Romantic Value-最小割+数值转化
    python中and和or的使用方法
    WP8加入自己定义铃声
    OpenCV-Python教程(4、形态学处理)
    [置顶] Bug 11775332
    Pyhon安装media模块
    hadoop集群环境搭建
    ubuntu12 环境下编译freerdp
    二分查找(非递归JAVA)
  • 原文地址:https://www.cnblogs.com/wzc521/p/11219339.html
Copyright © 2011-2022 走看看