zoukankan      html  css  js  c++  java
  • [CF1200E]Tourism

    题面描述

    给定一个n个点,m条边的无向图,其中你在第i个点建立旅游站点的费用为Ci。在这张图中,任意两点间不存在节点数超过10的简单路径。请找到一种费用最小的建立旅游站点的方案,使得每个点要么建立了旅游站点,要么与它有边直接相连的点里至少有一个点建立了旅游站点。

    输入格式

    第一行包含两个正整数n,m(1<=n<=20000,0<=m<=25000),分别表示点数和边数。
    第二行包含n个整数,其中第i个数为Ci(0<=Ci<=10000),表示在第i个点建立旅游站点的费用。
    接下来m行,每行两个正整数u,v(1<=u,v<=n),表示u与v之间连了一条边,保证没有重边。

    输出格式

    输出一行一个整数,即最小的总费用。

    样例数据

    样例输入

    3
    1 2 3

    样例输出

    1
    2

    题解

    直接dfs暴力查找最优解即可。中间需判断到达一个点后还能否继续移动到其它点。如果可以,则将这条支路上的贡献一并加入总的答案中。同时,当一个点被到达后我们需要判断是否走进了回路。这里可以记录之前到达的路径,如果发现重复的路径则说明进入了回路。
    这里贴出未剪枝的代码。

    #include<bits/stdc++.h>
    #define int long long
    #define maxn 200005
    #define maxm 200005
    using namespace std;
    inline char get(){
    	static char buf[30000],*p1=buf,*p2=buf;
    	return p1==p2 && (p2=(p1=buf)+fread(buf,1,30000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read(){
    	register char c=get();register int f=1,_=0;
    	while(c>'9' || c<'0')f=(c=='-')?-1:1,c=get();
    	while(c<='9' && c>='0')_=(_<<3)+(_<<1)+(c^48),c=get();
    	return _*f;
    }
    struct edge{
    	int u,v,w,next;
    }E[maxm<<1];
    int p[maxn],eid;
    inline void init(){
    	for(register int i=0;i<maxn;i++)p[i]=-1;
    	eid=0;
    }
    inline void insert(int u,int v,int w){
    	E[eid].u=u;
    	E[eid].v=v;
    	E[eid].w=w;
    	E[eid].next=p[u];
    	p[u]=eid++;
    }
    inline void insert2(int u,int v,int w){
    	insert(u,v,w);
    	insert(v,u,w);
    }
    int n,m,a[maxn],s;
    int vis[maxn];
    int dfs(int u,int last,int w,int deep){
    	if(deep>n+5)return w;
    	w+=a[u];
    	//cout<<u<<" "<<deep<<endl;
    	//cout<<u<<" "<<last<<" "<<a[u]<<" "<<w<<endl;
    	int save=a[u];
    	a[u]=0;
    	int ret=0;
    	for(register int i=p[u];~i;i=E[i].next){
    		int v=E[i].v;
    		//cout<<v<<" "<<vis[i]<<endl;
    		vis[i]=1;
    		if(v==last && (vis[i] || vis[i ^ 1]))continue;
    		//cout<<v<<"<>"<<vis[i]<<endl;
    		ret=max(ret,dfs(v,u,w,deep+1));
    		vis[i]=0;
    	}
    	a[u]=save;
    	if(ret==0)return w;
    	return ret;
    }
    signed main(){
    	//freopen("1.txt","r",stdin);
    	init();
    	n=read(),m=read();
    	for(register int i=1;i<=n;i++)a[i]=read();
    	for(register int i=1;i<=m;i++){
    		int u=read(),v=read();
    		insert2(u,v,1);
    	}
    	s=read();
    	cout<<dfs(s,-1,0,0); 
    	return 0;
    }
    
  • 相关阅读:
    Ubuntu下VSFTPD(五)(匿名FTP设置方法)
    Ubuntu下VSFTPD(六)(常见FTP命令及其功能) (
    ubuntu13.04装配oracle11gR2
    oracle之报错:ORA-00054: 资源正忙,要求指定 NOWAIT_数据库的几种锁
    oracle建索引的可选项
    Oracle自定义函数
    C# WinForm开发系列
    为C#自定义控件添加自定义事件
    python 爬虫抓取心得
    C# 正则表达式学习
  • 原文地址:https://www.cnblogs.com/Chen574118090/p/11620674.html
Copyright © 2011-2022 走看看