标签:name 可行性 cto 关系 void ons 思路 lse names
https://nanti.jisuanke.com/t/39271
题目大意:
当前有两个人,然后有n个点,每个点都有权值。然后给你m个对应关系,每一次的对应关系给你两个数,t1 和 t2 ,代表这两个不能在一个人手里。然后让你分配这n个点,使得这两个人的
差距进尽可能的小。然后输出大的那个。
具体思路:
对于每一个联通图,我们二分图染色,dp[i]表示当前这个差值能不能到达,这个过程可以通过可行性背包来解决。然后找一个最小的差值就可以了。
AC代码:
1 #include<bits/stdc++.h>
2 using namespace std;
3 # define ll long long
4 # define inf 0x3f3f3f3f
5 const int maxn = 2e5+100;
6 int a[maxn];
7 vector<int>Edge[maxn];
8 int vis[maxn];
9 int sum_0,sum_1;
10 void dfs(int u,int type){
11 if(!type)sum_0+=a[u];
12 else sum_1+=a[u];
13 vis[u]=1;
14 for(int i=0;i<Edge[u].size();i++){
15 int to=Edge[u][i];
16 if(vis[to])continue;
17 dfs(to,type^1);
18 }
19 }
20 int dp[maxn],pre[maxn];
21 int main(){
22 int T;
23 scanf("%d",&T);
24 while(T--){
25 int n,m,sum=0;
26 scanf("%d %d",&n,&m);
27 for(int i=0;i<=n;i++){vis[i]=0;Edge[i].clear();}
28 for(int i=1;i<=n;i++){
29 scanf("%d",&a[i]);
30 a[i]/=100;
31 sum+=a[i];
32 }
33 for(int i=0;i<=sum;i++){dp[i]=0;pre[i]=0;}
34 int st,ed;
35 for(int i=1;i<=m;i++){
36 scanf("%d %d",&st,&ed);
37 Edge[st].push_back(ed);
38 Edge[ed].push_back(st);
39 }
40 dp[0]=1;
41 for(int i=1;i<=n;i++){
42 if(vis[i])continue;
43 sum_0=0,sum_1=0;
44 dfs(i,0);
45 int tmp=abs(sum_0-sum_1);
46 for(int j=0;j<=sum;j++){
47 if(!dp[j])continue;
48 if(j+tmp<=sum)pre[j+tmp]=1;
49 if(abs(j-tmp)>=0)pre[abs(j-tmp)]=1;
50 }
51 for(int j=0;j<=sum;j++){
52 dp[j]=pre[j];
53 pre[j]=0;
54 }
55 }
56 for(int i=0;i<=sum;i++){
57 if(!dp[i])continue;
58 printf("%d\n",(i+sum+1)/2*100);
59 break;
60 }
61 }
62 return 0;
63 }
Miku and Generals(可行性背包) 西安邀请赛
标签:name 可行性 cto 关系 void ons 思路 lse names
原文地址:https://www.cnblogs.com/letlifestop/p/10935745.html