• bzoj4514: [Sdoi2016]数字配对--费用流


    看了一眼题目&数据范围,觉得应该是带下界的费用流

    原来想拆点变成二分图,能配对的连边,跑二分图,可行性未知

    后来看到另外一种解法。。

    符合匹配要求的数要满足:质因子的个数相差为1,且两者可整除

    因此筛完素数、分解质因子,记录质因子的个数

    奇数个分为一类,偶数个分为一类,那么连边一定是奇数向偶数才可以连,而其中能整除的且商为质数的连边

    然后源点向奇数的点连边,偶数的点向汇点连边,跑费用流

    至于下界,我们先把权值取负

    由于是求最小费用,那么当求得费用刚好大于0时

    上一次刚好小于零的费用流就是最终的流

    答案就是上一次的流量

    程序写的不是很简洁。。有些细节比如要开LL值得注意= =

      1 #include<stdio.h>
      2 #include<algorithm>
      3 #include<string.h>
      4 #include<vector>
      5 #include<queue>
      6 #define LL long long
      7 #define INF 0x7fffffff
      8 #define maxe 40000*2+10
      9 #define maxn 1000
     10 using namespace std;
     11 struct node{
     12     int from,to,flow,next;
     13     LL cost;
     14 }e[maxe];
     15 int ans,cnt,head[maxn],pre[maxn],vis[maxn];
     16 int n,s,t,a[maxn],b[maxn],notprime[32010],odd[maxn],even[maxn];
     17 LL c[maxn],sum,dis[maxn];
     18 vector<int> prime;
     19 
     20 void insert(int u, int v, int f, LL c){
     21     e[++cnt].from=u;
     22     e[cnt].to=v;
     23     e[cnt].flow=f;
     24     e[cnt].cost=c;
     25     e[cnt].next=head[u];
     26     head[u]=cnt;
     27     e[++cnt].from=v;
     28     e[cnt].to=u;
     29     e[cnt].flow=0;
     30     e[cnt].cost=-c;
     31     e[cnt].next=head[v];
     32     head[v]=cnt;
     33 }
     34 
     35 void init(){
     36     scanf("%d", &n);
     37     for (int i=1; i<=n; i++) scanf("%d", &a[i]);
     38     for (int i=1; i<=n; i++) scanf("%d", &b[i]);
     39     for (int i=1; i<=n; i++) scanf("%lld", &c[i]);
     40 }
     41 
     42 bool judge(int i, int j){
     43     if (!a[i] || !a[j] || a[i]%a[j] && a[j]%a[i]) return 0;
     44     int tmp=max(a[i]/a[j], a[j]/a[i]);
     45     for (int k=0; k<prime.size(); k++)
     46         if (prime[k]>=tmp) break;
     47         else if (tmp % prime[k]==0) return 0;
     48     return 1;
     49 }
     50 
     51 void get_prime(){
     52     memset(notprime,0,sizeof(notprime));
     53     for (int i=2; i<=32000; i++)
     54         if (!notprime[i]){
     55             prime.push_back(i);
     56             for (int j=i*i; j<=32000; j+=i)
     57                 notprime[j]=1;
     58         }
     59 } 
     60 
     61 void build(){
     62     odd[0]=even[0]=0;
     63     for (int i=1; i<=n; i++){
     64         int sum=0;
     65         for (int j=0; j<prime.size(); j++){
     66             int tmp=a[i];
     67             while (tmp%prime[j]==0) tmp/=prime[j],sum++;
     68         }
     69         if (sum&1) odd[++odd[0]]=i;
     70         else even[++even[0]]=i;
     71     }
     72     
     73     cnt=-1;
     74     memset(head,-1,sizeof(head));
     75     memset(e,0,sizeof(e));
     76     
     77     for (int i=1; i<=odd[0]; i++)
     78         for (int j=1; j<=even[0]; j++)
     79             if (judge(odd[i], even[j]))
     80                 insert(odd[i],even[j],INF,-c[odd[i]]*c[even[j]]);
     81     s=n+1; t=n+2;
     82     for (int i=1; i<=odd[0]; i++)
     83         insert(s,odd[i],b[odd[i]],0);
     84     for (int i=1; i<=even[0]; i++)
     85         insert(even[i],t,b[even[i]],0);
     86 }
     87 
     88 bool spfa(){
     89     memset(pre,-1,sizeof(pre));
     90     memset(dis,127,sizeof(dis));
     91     queue<int> Q;
     92     Q.push(s);
     93     dis[s]=0; vis[s]=1;
     94     while (!Q.empty()){
     95         int now=Q.front();
     96         Q.pop();
     97         vis[now]=0;
     98         for (int i=head[now]; i!=-1; i=e[i].next){
     99             int v=e[i].to;
    100             if (e[i].flow>0 && dis[v]>dis[now]+e[i].cost){
    101                 dis[v]=dis[now]+e[i].cost;
    102                 pre[v]=i;
    103                 if (!vis[v]){
    104                     vis[v]=1;
    105                     Q.push(v);
    106                 }
    107             }
    108         }
    109     }
    110     if (pre[t]==-1) return 0; return 1;
    111 }
    112 
    113 bool flow(){
    114     int f=INF;
    115     for (int i=pre[t]; i!=-1; i=pre[e[i^1].to]) f=min(f,e[i].flow);
    116     if ((LL)sum+dis[t]*f<=0){
    117         for (int i=pre[t]; i!=-1; i=pre[e[i^1].to]){
    118             e[i].flow-=f; e[i^1].flow+=f;
    119         }
    120         sum+=dis[t]*f;
    121         ans+=f;
    122         return 1;
    123     }
    124     else{
    125         ans-=(sum/dis[t]); 
    126         return 0;
    127     }
    128 }
    129 
    130 void work(){
    131     ans=0; sum=0;
    132     while (spfa() && flow());
    133     printf("%d
    ", ans);
    134 }
    135 
    136 int main(){
    137     get_prime();
    138     init();
    139     build();
    140     work();
    141     return 0;
    142 }
  • 相关阅读:
    No enclosing instance of type Test is accessible. Must qualify the allocation with an enclosing instance of type Test (e.g. x.new A() where x is an instance of Test).
    java中的static
    java gui 2
    Java GUI
    Java练习2
    安装docker后,原来正常的vagrant up启动出现了错误
    PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 17295719 bytes) in
    Class 'ZipArchive' not found解決
    从google storage上传或者下载文件
    使用python获取pptx文件的文本内容范例
  • 原文地址:https://www.cnblogs.com/mzl0707/p/5438390.html
Copyright © 2020-2023  润新知