UVa12118:Inspector's Dilemma

题目大意:

有一个有V(V<=1000)个节点的图,每两个点之间都有边连接,所有边长为T。先给出E条指定的边,找出一条最短路(起点终点随意),使这条路径经过所有给定的边。

分析:

首先想一想,要是所有的边都没有公共节点该多好。那么答案就是(E-1)*T了。
可惜并不是这样,那么,我们就可以把几个有公共端点的边看成一个子图。对于一个子图,它要有一条边连接进来,再有一条边连出去(入口出口除外)。
所以就想到一个方法,对于一个子图,我们要在原图中加几条边使它联通,再把他们穿起来。想到了什么?欧拉道路!对于一个子图,我们把它变成一个”一笔画”图,添加的边数加上E,再加上连接各个子图的路径就是答案!

所以算法出来了:我们先统计各个点的度数,再DFS各个子图,求出要加上的边数,再用上文的方法就是解(这里用并查集不大方便,反正题目给的范围小,DFS更快捷)。

#include <cstdio>
#include <vector>
#include <set>
#include <cstdlib>
#include <cstring>

using namespace std;
const int maxn=1000+20;

int dgr[maxn];
bool a[maxn];
vector<int> pile[maxn];

int dfs(int k)
{
 int ans=0;
 if (dgr[k]) ans++; //奇点,增加答案

 for (int i=0;i<pile[k].size();i++)
 {
  int next=pile[k][i];
  if (!a[next]) {a[next]=1;ans+=dfs(next);}
 }
 return ans;
}

int main()
{
  int x,y,v,e,t,ca=0;
  while ((scanf("%d%d%d",&v,&e,&t)==3) && (v || e || t)) //注意:有可能有V不为0,而E为0的情况
  {
   if ((e==0) || (v==0)) {printf("Case %d: 0\n",++ca);continue;} // 特殊判断
   for (int i=0;i<v;i++) pile[i].clear(); //邻接表存边

   memset(dgr,0,sizeof(dgr)); //度数,因为只要奇偶性,没必要存储实际度数
   set<int> node; //给定的边涉及的点
   node.clear();

   for (int i=0;i<e;i++)
   {
    scanf("%d%d",&x,&y);
    dgr[x]=1-dgr[x];
    dgr[y]=1-dgr[y];  //改变奇偶性
    node.insert(x);
    node.insert(y);
    pile[x].push_back(y);
    pile[y].push_back(x);
   }

   set<int>::iterator it;
   memset(a,0,sizeof(a)); //遍历标记

   int ans=e-1; //因为有n个子图时,要加n-1条路径,下面加了n个,所以-1

   for (it=node.begin();it!=node.end();it++) 
    if (!a[*it]) 
    {
     ans++; //子图之间的路径
     a[*it]=1;
     int p=dfs(*it); //子图奇点数
     if (p>0) ans+=(p-2)/2; //加一条边少两个奇点,一个子图可以留两个奇点作为出入口 
    }

   printf("Case %d: %d\n",++ca,ans*t);
  }
  return 0;
}

想想子图的问题,是不是很像tarjan呢……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值