Codeforces Round #284 (Div. 1) B. Name That Tune(最大流)

题目链接

D. Traffic Jams in the Land
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Some country consists of (n + 1) cities, located along a straight highway. Let's number the cities with consecutive integers from 1 to n + 1 in the order they occur along the highway. Thus, the cities are connected by n segments of the highway, the i-th segment connects cities number i and i + 1. Every segment of the highway is associated with a positive integer ai > 1 — the period of traffic jams appearance on it. 

In order to get from city x to city y (x < y), some drivers use the following tactics. 

Initially the driver is in city x and the current time t equals zero. Until the driver arrives in city y, he perfors the following actions:

  • if the current time t is a multiple of ax, then the segment of the highway number x is now having traffic problems and the driver stays in the current city for one unit of time (formally speaking, we assign t = t + 1); 
  • if the current time t is not a multiple of ax, then the segment of the highway number x is now clear and that's why the driver uses one unit of time to move to city x + 1 (formally, we assign t = t + 1 and x = x + 1). 

You are developing a new traffic control system. You want to consecutively process q queries of two types:

  1. determine the final value of time t after the ride from city x to city y (x < y) assuming that we apply the tactics that is described above. Note that for each query t is being reset to 0. 
  2. replace the period of traffic jams appearing on the segment number x by value y (formally, assign ax = y). 

Write a code that will effectively process the queries given above.

Input

The first line contains a single integer n (1 ≤ n ≤ 105) — the number of highway segments that connect the n + 1 cities.

The second line contains n integers a1, a2, ..., an (2 ≤ ai ≤ 6) — the periods of traffic jams appearance on segments of the highway.

The next line contains a single integer q (1 ≤ q ≤ 105) — the number of queries to process.

The next q lines contain the descriptions of the queries in the format cxy (c — the query type). 

If c is character 'A', then your task is to process a query of the first type. In this case the following constraints are satisfied: 1 ≤ x < y ≤ n + 1.

If c is character 'C', then you need to process a query of the second type. In such case, the following constraints are satisfied: 1 ≤ x ≤ n2 ≤ y ≤ 6.

Output

For each query of the first type output a single integer — the final value of time t after driving from city x to city y. Process the queries in the order in which they are given in the input.

Examples
input
10
2 5 3 2 3 5 3 4 2 4
10
C 10 6
A 2 6
A 1 3
C 3 4
A 3 11
A 4 9
A 5 6
C 7 3
A 8 10
A 2 5
output
5
3
14
6
2
4
4

题意:给定一个长度为n的数组,已经m组下标对应关系(下标之和为奇数)现在可以进行如下操作:

从m组对应关系中选出一组,同除一个公约数

问最多能进行多少次这样的操作

题解:

首先,这是一个二分图,因为有关系的两个点属于不同的集合。又因为一百个数最多3200个素数,然后暴力对每个素数跑最大流就好。

建图就是先对m对关系建边,设边的容量无穷大,然后源点向第一集合的数建边容量为当前枚举的素数在这个数中的个数,第二集合的数向汇点简便容量为当前枚举的素数在这个数中的个数。然后将对每个素数跑出来的结果相加就是答案。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
int a[110];
VI v;
const int maxn=100+10;//点数的最大值
const int maxm=1000;//边数的最大值
struct Node
{
    int from,to,next;
    int cap;
}edge[maxm];
int tol;
int dep[maxn];//dep为点的层次
int head[maxn];
void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)//第一条边下标必须为偶数
{
    edge[tol].from=u;
    edge[tol].to=v;
    edge[tol].cap=w;
    edge[tol].next=head[u];
    head[u]=tol++;
    edge[tol].from=v;
    edge[tol].to=u;
    edge[tol].cap=0;
    edge[tol].next=head[v];
    head[v]=tol++;
}
int BFS(int start,int end)
{
    int que[maxn];
    int front,rear;
    front=rear=0;
    memset(dep,-1,sizeof(dep));
    que[rear++]=start;
    dep[start]=0;
    while(front!=rear)
    {
        int u=que[front++];
        if(front==maxn)front=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].cap>0&&dep[v]==-1)
            {
                dep[v]=dep[u]+1;
                que[rear++]=v;
                if(rear>=maxn)rear=0;
                if(v==end)return 1;
            }
        }
    }
    return 0;
}
int dinic(int start,int end)
{
    int res=0;
    int top;
    int stack[maxn];//stack为栈,存储当前增广路
    int cur[maxn];//存储当前点的后继
    while(BFS(start,end))
    {
        memcpy(cur,head,sizeof(head));
        int u=start;
        top=0;
        while(1)
        {
            if(u==end)
            {
                int min=inf;
                int loc;
                for(int i=0;i<top;i++)
                    if(min>edge[stack[i]].cap)
                    {
                        min=edge[stack[i]].cap;
                        loc=i;
                    }
                for(int i=0;i<top;i++)
                {
                    edge[stack[i]].cap-=min;
                    edge[stack[i]^1].cap+=min;
                }
                res+=min;
                top=loc;
                u=edge[stack[top]].from;
            }
            for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
                if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
                    break;
            if(cur[u]!=-1)
            {
                stack[top++]=cur[u];
                u=edge[cur[u]].to;
            }
            else
            {
                if(top==0)break;
                dep[u]=-1;
                u=edge[stack[--top]].from;
            }
        }
    }
    return res;
}
VI V;
PII q[110];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    rep(i,1,n+1) scanf("%d",&a[i]);
    int st=0,ed=n+1;
    rep(i,1,m+1)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        if(a&1)
            q[i]=make_pair(a,b);
        else q[i]=make_pair(b,a);
    }
    V.clear();
    rep(i,1,n+1)
    {
        int t=a[i];
        for(int j=2;j*j<=t&&t;j++)
        {
            if(t%j==0)
            {
                V.pb(j);
                while(t%j==0&&t) t/=j;
            }
        }
        if(t&&t!=1) V.pb(t);
    }
    sort(V.begin(),V.end());
    V.erase(unique(V.begin(),V.end()),V.end());
    int ans=0;
    rep(i,0,V.size())
    {
        tol=0;
        rep(i,st,ed+1) head[i]=-1;
        rep(j,1,n+1)
        {
            int cnt=0;
            int t=a[j];
            while(t%V[i]==0&&t)
            {
                t/=V[i];
                cnt++;
            }
            if(j&1)
                addedge(st,j,cnt);
            else addedge(j,ed,cnt);
        }
        rep(i,1,m+1)
        {
            addedge(q[i].fi,q[i].se,inf);
        }
        ans+=dinic(st,ed);
    }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/tarjan/p/7247461.html