zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:Graph(图论+贪心)

    题目描述

      给定一张$n$个点$m$条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通你想在这张图上进行若干次旅游,每次旅游可以任选一个点$x$作为起点,再走到一个与 $x$直接有边相连的点$y$,再走到一个与$y$直接有边相连的点$z$并结束本次旅游

      作为一个旅游爱好者,你不希望经过任意一条边超过一次,注意一条边不能即正向走一次又反向走一次,注意点可以经过多次,在满足此条件下,你希望进行尽可能多次的旅游,请计算出最多能进行的旅游次数并输出任意一种方案


    输入格式

    第$1$行两个正整数$n$与$m$,表示全图的点数与边数
    下接$m$行,每行两个数字$u$与$v$表示一条边


    输出格式

    第$1$行一个整数$cnt$表示答案
    下接$cnt$行,每行三个数字$x,y$与$z$,表示一次旅游的路线
    如有多种旅行方案,任意输出一种即可


    样例

    样例输入:

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

    样例输出:

    2
    4 1 2
    4 3 2


    数据范围与提示

    对于前$20\%$的数据,$nleqslant 10,mleqslant 20$
    对于令$20\%$的数据,$m=n−1$,并且图连通
    对于令$10\%$的数据,每个点的度数不超过$2$
    对于$100\%$的数据,$nleqslant 100,000,mleqslant 200,000$


    题解

    如果你做过下面这两道题的其中一道,这道题就会显得简单多了:

      $alpha.$虎。

      $eta.w$。

    题不一样,但是思路是类似的。

    对于树和链,我们显然是从叶子节点开始一定最优。

    那么考虑一般情况,利用上面那两道题的思路(尤其是虎),也有点类似无修支配树,总之都是贪心……

    时间复杂度:$Theta(n)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    struct rec{int nxt,to;}e[400001];
    struct node{int x,y,z;};
    int head[100001],cnt=1;
    int n,m;
    int depth[100001];
    vector<node> ans;
    void add(int x,int y)
    {
    	e[++cnt].nxt=head[x];
    	e[cnt].to=y;
    	head[x]=cnt;
    }
    int dfs(int x)
    {
    	int res=0;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		if(!depth[e[i].to])
    		{
    			depth[e[i].to]=depth[x]+1;
    			int flag=dfs(e[i].to);
    			if(flag)ans.push_back((node){flag,e[i].to,x});
    			else
    			{
    				flag=e[i].to;
    				if(res){ans.push_back((node){flag,x,res});res=0;}
    				else res=flag;
    			}
    		}
    		else
    		{
    			if(depth[e[i].to]>depth[x])
    			{
    				int flag=e[i].to;
    				if(flag)
    				{
    					if(res){ans.push_back((node){flag,x,res});res=0;}
    					else res=flag;
    				}
    			}
    		}
    	}
    	return res;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);add(y,x);
    	}
    	for(int i=1;i<=n;i++)
    		if(!depth[i])
    		{
    			depth[i]=1;
    			dfs(i);
    		}
    	printf("%d
    ",ans.size());
    	for(int i=0;i<ans.size();i++)printf("%d %d %d
    ",ans[i].x,ans[i].y,ans[i].z);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    6、scala面向对象-对象
    C# App.config配置文件的讲解
    abstract、override、new、virtual、sealed使用和示例
    C# 枚举的使用
    深入浅出面向对象分析与设计
    数据契约(DataContract)的作用
    C# 启动停止SQLServer数据库服务器
    C# 定时器计划任务
    C# 程序只能执行一次
    WPF dataGrid中的check的改变事件
  • 原文地址:https://www.cnblogs.com/wzc521/p/11629289.html
Copyright © 2011-2022 走看看