TC srm 632 div1

Problem Statement

    
Alice is going to host a competition in running, called the Candy Cup. Candy Cup will take place in a city that consists of N intersections. The intersections are numbered 0 through N-1.

There are M roads in the city. The roads are numbered 0 through M-1. Each road is bidirectional and connects two intersections. There are no self-loops. Each pair of intersections is directly connected by at most one road. Note that the road network is not guaranteed to be connected. (That is, it may be impossible to travel between some pairs of intersections.)


You are given the description of the city: the int N and two vector <int>s A and B, each with M elements. For each valid i, the road number i connects the intersections A[i] and B[i].

As a preparation for the Candy Cup, Alice has placed some candies into the middle of each road. For each i, she placed exactly 3^i (three to the power of i) candies into the middle of road i.

The rules of Candy Cup are really simple. Each participant starts at the intersection 0 and must reach intersection N-1 by following some roads. Additionally, each time a participant takes a road, they must pick up a candy from that road. (Once there are no candies left on a road, participants in the race are not allowed to take that road.) Note that different participants may use a different number of roads to reach the finish.

Let F be the largest possible number of participants that can finish Candy Cup by reaching the finish in a valid way. Return the value (F modulo 1,000,000,007).
Definition
    
Class:
CandyCupRunningCompetition
Method:
findMaximum
Parameters:
int, vector <int>, vector <int>
Returns:
int
Method signature:
int findMaximum(int N, vector <int> A, vector <int> B)
(be sure your method is public)
Limits
    
Time limit (s):
2.000
Memory limit (MB):
256
Constraints
-
N will be between 2 and 2000, inclusive.
-
A and B will contain between 0 and 2,000 elements, inclusive.
-
A and B will each contain the same number of elements.
-
Each element of A and B will be between 0 and N-1, inclusive.
-
No two roads will connect the same pair of intersections.
-

For each valid i, A[i] will be different from B[i].

题目大意:给你n个点,编号为0~n-1,m条边,边有编号从0~m-1,编号为i的边,边权为3^i。然后问你从0号节点到n-1号节点的最大流!!

解题思路:很明显是一个最大流,但是n最大为2000,边最多有4*10^6,显然网络流根本跑不出来,(师兄说,如果边比较少,有可能跑出来。。。)然后,某神牛给了一个思路是贪心!!怎么贪心,完全想不到啊。。。。因为权值是离散的(这个我也知道,但是有什么用呢?),将边权从大往小扫描,如果加入当前的边,使得0和n-1连通,那么这条边一定是最小割的一条边(可以证明在这条边之前加入的边,权值至少是这条边的3倍!肯定用不完);否则将这条边加入并查集!

详见代码,思路真是太神了!!

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
using namespace std;

const int N = 100005;
const ll MOD = 1000000007;

class CandyCupRunningCompetition
{
private:
    vector<int> fa;
    void init(int n)
    {
        for(int i=0;i<n;i++) fa.PB(i);
    }
    int find_fa(int r)
    {
        if(fa[r]==r) return r;
        return fa[r]=find_fa(fa[r]);
    }
    void unio(int i,int j)
    {
        fa[find_fa(i)]=find_fa(j);
    }
    ll quick_pow(int k)
    {
        ll res=1LL;
        ll t=3;
        while(k>0)
        {
            if(k&1) res=(res*t)%MOD;
            t=(t*t)%MOD;
            k>>=1;
        }
        return res;
    }
public:
    int findMaximum(int n, vector <int> a, vector <int> b)
    {
        fa.clear();
        init(n);
        ll ans=0LL;
        for(int i=a.size()-1;i>=0;i--)
        {
            vector<int> bf=fa;
            unio(a[i],b[i]);
            if(find_fa(0)==find_fa(n-1))
            {
                ans=(ans+quick_pow(i))%MOD;
                fa=bf;
            }
        }
        return (int)ans;
    }
} tmp;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章