正题
题目大意
有nnn个点mmm条边,若一个点没选,那么连接到的点都得选择。求最小选择权值。
解题思路
对于每个联通块暴力dfsdfsdfs,若一个点不选那么就把别的点都选上。
因为每个点至少限制一个点,那么时间复杂度最坏为O(2n2)O(2^{\frac{n}{2}})O(22n)(也就是一条链的情况)。
codecodecode
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=60;
int tot,in[N],ans,w[N],flag[N],n,maxs,m,ls[N];
bool v[N],zh[N];
struct node{int to,next;
}a[N*20];
void addl(int x,int y)
{a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
void dfs(int x)
{in[++tot]=x;v[x]=1;for(int i=ls[x];i;i=a[i].next)if(!v[a[i].to])dfs(a[i].to);
}
void get_ans(int dep,int z)
{if(z>maxs) return;if(dep>tot){maxs=min(maxs,z);return;}get_ans(dep+1,z+w[in[dep]]);if(!flag[in[dep]]&&!zh[in[dep]]){for(int i=ls[in[dep]];i;i=a[i].next)flag[a[i].to]++;get_ans(dep+1,z);for(int i=ls[in[dep]];i;i=a[i].next)flag[a[i].to]--;}
}
int main()
{//freopen("graph.in","r",stdin);//freopen("graph.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&w[i]);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);if(x==y) zh[x]=1;}for(int i=1;i<=n;i++){maxs=2147483647;tot=0; if(v[i]) continue;dfs(i);get_ans(1,0);ans+=maxs;}printf("%d",ans);
}