JZOJ 4252. 【五校联考7day2】QYQ的图

题目

Description

给你一个n个点,m条边的无向图,每个点有一个非负的权值ci,现在你需要选择一些点,使得每一个点都满足:
如果这个点没有被选择,则与它有边相连的所有点都必须被选择。
问:满足上述条件的点集中,所有选择的点的权值和最小是多少?
QYQ很快就解决了这个问题,但是他已经回到了左下角……没有留下答案,现在只好请你来解决这个问题啦!
 

Input

从文件graph.in中输入数据。
输入的第一行包含两个整数n,m
输入的第二行包含n个整数,其中第i个整数代表ci
输入的第三行到第m+2行,每行包含两个整数u,v,代表点u和点v之间有一条边

Output

输出到文件graph.out中。
输出的第一行包含一个整数,代表最小的权值和
 

Sample Input

3 1
1 2 3
3 1

Sample Output

1
样例说明:
只选择1号点,满足题意
 

Data Constraint

对于20% 的数据:n<=10
对于40%的数据:n<=20
对于100%的数据:1<=n<=50, 1<=m<=500, 0<=c<=1000
图中可能会有重边,自环。
点的编号为1—n。

 

分析

  • 暴力
  • 但是要注意优化 sum>=ans
  • 然后。。。

          

代码

 1 #pragma GCC optimize(2)
 2 #include<fstream>
 3 #include<cstring>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #define ll long long
 8 using namespace std;
 9 ll n,m;
10 vector <int> f[10001];
11 ll a[10001],b[10001];
12 ll flag[10001];
13 ll anss=0x3f3f3f3f,cnt,ans;
14 void dfs(ll p,ll sum)
15 {
16     if (sum>=anss) return;
17     if (p>n)   {anss=sum;return;}
18     flag[p]++; dfs(p+1,sum+a[p]); flag[p]--;
19     if (!flag[p])
20     {
21         for (int i=0;i<f[p].size();i++)
22             flag[f[p][i]]++;
23         dfs(p+1,sum);
24         for (int i=0;i<f[p].size();i++)
25             flag[f[p][i]]--;
26     }
27 }
28 inline ll read()
29 {
30     ll p=0,f=1;char c=getchar();
31     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
32     while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
33     return f*p;
34 }
35 int main ()
36 {
37     freopen("graph.in","r",stdin);
38     freopen("graph.out","w",stdout);
39     n=read();
40     m=read();
41     for (int i=1;i<=n;i++)
42         a[i]=read();
43     for (int i=1,x,y;i<=m;i++)
44     {
45         x=read();
46         y=read();
47         if (x==y&&!flag[x])
48             flag[x]=1;
49         f[x].push_back(y);
50         f[y].push_back(x);
51     }
52     dfs(1,0);
53     printf("%lld",anss);
54 }
为何要逼自己长大,去闯不该闯的荒唐
原文地址:https://www.cnblogs.com/zjzjzj/p/10339529.html