zoukankan      html  css  js  c++  java
  • 2013多校第二场

    hdu 4611

    题意:求累加abs(i%a - i%b)的和,(o<=i<n);

    分析:首先a,b大小无关,不妨设a<b,通过枚举几项,发现按照每a个来分,abs(i%a-i%b)在大部分区间里的值是相同的,只有在k*b属于这个区间里的时候发生变化(因为余数都是递增的只有在k*b出现后从b-1变成0);

    所以我们不妨枚举按长度为a来枚举起点,如果k*b属于这个区间就另外处理,当到达循环节后直接处理到最终余数部分继续枚举,最后如果大于n就break,并且减去多加的部分;

    对于样例:21   2   5

    0  1   2   3   4   5   6   7   8   9   10   11   12   13 14    15    ..... 21

    0   1   0  1   0   1   0    1   0    1   0     1      0      1    0    1

    0   1   2   3  4   0   1    2    3    4   0    1      2     3    4    0        

    每2个一组,每组的对应位置差值是相同,可以o(1)处理每一组,

    第三组因为4在里面,所以分成两段,也可以o(1)处理,

    处理到最小公倍数10后可以一次处理到20,然后继续处理,最坏的情况下a,b很大且互质,时间复杂度O(max(a,b));

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<cstdlib>
     7 using namespace std;
     8 const int N = 10000;
     9 typedef long long LL;
    10 int gcd(int a,int b){
    11     if (b==0) return a;
    12     else return gcd(b,a%b);
    13 }
    14 int a,b,n;
    15 int main(){
    16     int T;scanf("%d",&T);
    17     while (T--){
    18         scanf("%d%d%d",&n,&a,&b);
    19         if (a>b) swap(a,b);
    20         int c = a/gcd(a,b)*b;
    21         int now = 0,now2 = b;
    22         LL ans = 0;
    23         while (now < n){
    24             if (now <= now2 && now2 < now+a){
    25                 ans +=(LL)abs(now%a-now%b)*(now2-now) + (LL)abs(now2%a-now2%b)*(now+a-now2);
    26                 now2 += b;
    27             }else {
    28                 ans += (LL)abs(now%a-now%b)*a;
    29             }    
    30             now += a;
    31             if (now == c){
    32                 ans = ans*(n/c);
    33                 now = n/c*c;
    34                 now2 = now + b;     
    35             }
    36         }
    37         if (now>=n){
    38             for (int i=now-1;i>=n;i--){
    39                 ans -= abs(i%a-i%b);
    40             }
    41             printf("%I64d
    ",ans);
    42             continue;
    43         }    
    44         printf("%I64d
    ",ans);
    45     }
    46     return 0;
    47 }
    View Code

    hdu 4614

    题意:2个操作,操作1一个清空一段区间所有值,操作2一个从i位置开始找到空的位置就插入值,如果到末尾还有值没有插入完也结束;

    分析:最终都转化为区间的更新,对于操作2只要二分找到最左边的起点和最右边的终点就可以了,基础的线段树区间更新;

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<cmath>
      6 #include<cstdlib>
      7 #include<vector>
      8 #define lson l,m,rt<<1
      9 #define rson m+1,r,rt<<1|1
     10 using namespace std;
     11 const int N = 50000+10;
     12 int col[N<<2],num[N<<2];
     13 int n,m;
     14 void pushup(int rt){
     15     num[rt] = num[rt<<1] + num[rt<<1|1];
     16 }
     17 void pushdown(int rt,int l,int m,int r){
     18     if (col[rt]!=-1){
     19         num[rt<<1] = col[rt] * (m-l+1);
     20            num[rt<<1|1] = col[rt] * (r-m);
     21         col[rt<<1] = col[rt<<1|1] = col[rt];    
     22         col[rt] = -1;
     23     }
     24 }
     25 void update(int L,int R,int c,int l,int r,int rt){
     26     if (L<=l && r<=R){
     27         col[rt] = c;
     28         num[rt] = (r-l+1)*c;
     29         return;
     30     }
     31     int m = (l+r)>>1;
     32     pushdown(rt,l,m,r);
     33     if (L<=m) update(L,R,c,lson);
     34     if (m <R) update(L,R,c,rson);
     35     pushup(rt);
     36 }
     37 int query(int L,int R,int l,int r,int rt){
     38     if (L<=l && r<=R){
     39         return num[rt];
     40     }
     41     int m = (l+r)>>1;
     42     pushdown(rt,l,m,r);
     43     int t1=0,t2=0;
     44     if (L<=m) t1 = query(L,R,lson);
     45     if (m< R) t2 = query(L,R,rson);
     46     return t1+t2;
     47 }
     48 int findl(int l,int r,int v){
     49     int ret;
     50     int up = r;
     51     while (r>=l){
     52         int m = (l+r)>>1;
     53         int t = up-m+1-query(m,up,0,n-1,1);
     54 
     55         if (t>=v){
     56             ret = m; l = m+1;
     57         }else r = m-1;
     58     }
     59     return ret;
     60 }
     61 int findr(int l,int r,int v){
     62     int ret;
     63     int lim = l;
     64     while (r>=l){
     65         int m =  (l+r)>>1;
     66         int t = m-lim+1-query(lim,m,0,n-1,1);
     67         if (t>=v){
     68             ret = m; r = m-1;
     69         }else l = m+1;
     70     }
     71     return ret;
     72 }
     73 void solve(int u,int v){
     74     int c = query(u,n-1,0,n-1,1);
     75     if (n-u==c){
     76         printf("Can not put any one.
    ");
     77         return;
     78     }
     79     c = n-u-c;
     80     int l = findl(u,n-1,c);
     81     if (c>v) c = v;
     82     int r = findr(u,n-1,c);
     83     printf("%d %d
    ",l,r);
     84     update(l,r,1,0,n-1,1);
     85 }
     86 int main(){
     87     int T;scanf("%d",&T);
     88     while (T--){
     89         scanf("%d%d",&n,&m);
     90         memset(col,-1,sizeof(col));
     91         memset(num,0,sizeof(num));
     92         for (int i=0;i<m;i++){
     93             int k,x,y;
     94             scanf("%d%d%d",&k,&x,&y);
     95             if (y>n-1) y = n-1;
     96             if (x< 0 ) x =0;
     97             if (k == 1){
     98                 solve(x,y);
     99             }else {
    100                 int c = query(x,y,0,n-1,1);
    101                 printf("%d
    ",c);
    102                 update(x,y,0,0,n-1,1);
    103             }
    104         }
    105         printf("
    ");
    106     }
    107     return 0;
    108 }
    View Code

    hdu 4617

    题意:给你n(<30)个无限长的圆柱,问圆柱之间最短的距离,如果相交就输出"LUCKY";

    分析:因为圆柱是无限长的,于是圆柱间的最短距离就是两条轴线的最短距离(两条异面直线的距离),最后只要判断下是否大于还是小于两个圆柱底面半径和就好了

    有板就行了。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<vector>
     5 #include<cstdio>
     6 #include<cstdlib>
     7 using namespace std;
     8 const double eps = 1e-8;
     9 const int N =30+10;
    10 inline int dcmp(double x){
    11     return x<-eps ? -1 : x>eps;
    12 }
    13 inline double sqr(double x){
    14     return x*x;
    15 }
    16 
    17 struct Point{
    18     double x,y,z;
    19     Point(double x=0,double y=0,double z=0):x(x),y(y),z(z){}
    20     Point operator + (const Point &p)const{
    21         return Point(x+p.x,y+p.y,z+p.z);
    22     }
    23     Point operator - (const Point &p)const{
    24         return Point(x-p.x,y-p.y,z-p.z);
    25     }
    26     Point operator * (const double &p)const{
    27         return Point(x*p,y*p,z*p);
    28     }
    29     Point operator / (const double &p)const{
    30         return Point(x/p,y/p,z/p);
    31     }
    32     void input(){
    33         scanf("%lf%lf%lf",&x,&y,&z);
    34     }
    35 
    36 };
    37 Point Cross(Point a,Point b){
    38     return Point(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z , a.x*b.y - a.y*b.x);
    39 }
    40 double Dot(Point a,Point b){
    41     return a.x*b.x+a.y*b.y+a.z*b.z;
    42 }
    43 double Length(Point a){
    44     return sqrt(Dot(a,a));
    45 }
    46 bool LineDistance(Point p1,Point u,Point p2, Point v,double &s){
    47     double b = Dot(u,u)*Dot(v,v) - Dot(u,v)*Dot(u,v);
    48     if (dcmp(b) == 0) return false; 
    49     double a = Dot(u,v)*Dot(v,p1-p2) - Dot(v,v)*Dot(u,p1-p2);
    50     s = a/b;
    51     return true;
    52 }
    53 double DistanceToLine(Point p,Point a,Point b){
    54     Point v1 = b - a, v2 = p - a;
    55     return Length(Cross(v1,v2)) / Length(v1);
    56 }
    57 double Distance(Point a,Point b){
    58     return sqrt( sqr(a.x-b.x) + sqr(a.y-b.y) +sqr(a.z-b.z));
    59 
    60 }
    61 Point ct[N],vec[N];
    62 double r[N];
    63 int n;
    64 
    65 void solve(){
    66     double mx = 100000000;
    67 
    68     for (int i =0;i<n;i++){
    69         for (int j=i+1;j<n;j++){
    70             double d,s;
    71             if (LineDistance(ct[i],vec[i],ct[j],vec[j],s)){
    72                 d = DistanceToLine(ct[i]+vec[i]*s,ct[j],ct[j]+vec[j]);
    73             }else {
    74                 d = DistanceToLine(ct[i],ct[j],ct[j]+vec[j]);
    75             }
    76             d -= r[i]+r[j];
    77             if (d<mx) mx = d;
    78         }
    79     }
    80     if (dcmp(mx)<=0) printf("Lucky
    ");
    81     else printf("%.2lf
    ",mx);
    82     
    83 }
    84 int main(){
    85     int T;scanf("%d",&T);
    86     while (T--){
    87         scanf("%d",&n);
    88         for (int i=0;i<n;i++){
    89             ct[i].input();
    90     
    91             Point t1,t2;
    92             t1.input(); t2.input();
    93             r[i]= Distance(ct[i],t1);
    94             vec[i] = Cross(t1-ct[i],t2-ct[i]); 
    95         }
    96         solve();
    97     }
    98     return 0;
    99 }
    View Code

    hdu 4618

    题意:给你一个n*m(n,m<300)的矩阵,求最大子正方形,每行每列是回文串。

    分析:为了出来方便,把矩阵构造一下,(按照manacher o(n)求回文串的方法)

    预处理出每一行每一列以每个结点为中心最大的回文串;

    然后在枚举每个点统计最大的回文正方形;  因为统计的时候复杂度就是O(N^3);

    所以在预处理每一行的时候也可以直接O(N^3)暴力处理不需要用manacher的方法了;

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<vector>
     7 #include<cmath>
     8 using namespace std;
     9 const int N = 600+10;
    10 int mz[N][N];
    11 int n,m;
    12 int c1[N][N],c2[N][N];
    13 int find(int x,int y){
    14     int k = 0;
    15     int ret = 1;
    16     int mx = 100000;
    17     while (1){
    18         if (c1[x-k][y] >= ret && c1[x+k][y] >=ret && c2[x][y-k] >=ret && c2[x][y+k] >= ret){
    19             if (c1[x-k][y]<mx) mx = c1[x-k][y];
    20             if (c1[x+k][y]<mx) mx = c1[x+k][y];
    21             if (c2[x][y-k]<mx) mx = c2[x][y-k];
    22             if (c2[x][y+k]<mx) mx = c2[x][y+k];
    23             ret++; k++;
    24         }else break;
    25         if (ret >= mx) break;
    26     }
    27     return ret;
    28 }
    29 void solve(){
    30     for (int i = 0; i <= 2*n; i++){
    31         for (int j = 0; j <= 2*m; j++){
    32             int k = 0;
    33             while (mz[i][j-k] == mz[i][j+k] && j-k>=0 && j+k<=2*m) k++;
    34             c1[i][j] = k;
    35         }
    36     }
    37     for (int i = 0; i <= 2*m; i++){
    38         for (int j = 0; j <= 2*n; j++){
    39             int k = 0;
    40             while (mz[j+k][i] == mz[j-k][i] && j+k<=2*n && j-k>=0) k++;
    41             c2[j][i] = k;
    42         }
    43     }
    44 
    45     int ret = 0;
    46     for (int i=0; i <= 2*n; i++){
    47         for (int j = 0; j <= 2*m; j++){
    48             int t = find(i,j);
    49             if (t>ret) ret = t;        
    50         }
    51     }
    52     printf("%d
    ",ret-1);
    53 
    54 }
    55 int main(){
    56     int T;scanf("%d",&T);
    57     while (T--){
    58         scanf("%d%d",&n,&m);
    59         memset(mz,0,sizeof(mz));
    60         for (int i = 0; i < n; i++){
    61             for (int j = 0; j < m; j++){
    62                 scanf("%d",&mz[i*2+1][j*2+1]);
    63             }
    64         }
    65         solve();
    66     }
    67     return 0;
    68 }
    View Code

    hdu 4616

    题意:给你一棵n-1个结点的树,每一结点有一个值ai[i],和一个bi[i]表示是否有陷阱,求最多经过m个陷阱能拿到的最大的价值,

    题目要求一旦碰到第m个陷阱游戏就结束;

    分析:就是从树上选一条链,链上的点是1的个数少于等于m个,如果等于m个那么至少一个端点要为1;

    设dp[rt][i][j],i==0表示从点rt出发经历了j个陷阱且结束端点不是陷阱,能获得的最大价值,

    i==1 表示从点rt出发经历了j个陷阱且结束端点是陷阱,能获得的最大价值;

    dfs();扫一遍,边扫边处理出以该点为根的子树能得到的满足条件的最大值;

    然后就变成一道模拟题了,我用了非常麻烦的写法,对每一种状态都人肉更新,特别是合并两条链的地方;其实应该有很多地方的转移是没必要的;

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<vector>
      8 #pragma comment(linker, "/STACK:1024000000,1024000000") 
      9 using namespace std;
     10 const int N = 50000+10;
     11 vector<int > g[N];
     12 int dp[N][2][4];
     13 int n,m;
     14 int ai[N],bi[N];
     15 inline void Max(int &x,int y){
     16     x = max(x,y);
     17 }
     18 int ans;
     19 int find(int rt,int u,int v){
     20     int ret = 0;
     21     if (bi[rt] == 0){
     22         if (m == 1){
     23             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][0]);
     24             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][0]);
     25             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][1]);
     26         }else if (m == 2){
     27             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][0]);
     28             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][1]);
     29             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][1]);
     30             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][2]);
     31 
     32             Max(ret, dp[u][0][1]+ai[rt]+dp[v][0][0]);
     33             Max(ret, dp[u][0][1]+ai[rt]+dp[v][1][1]);
     34             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][0]);
     35             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][1]);
     36             Max(ret, dp[u][1][1]+ai[rt]+dp[v][1][1]);
     37         
     38             Max(ret, dp[u][1][2]+ai[rt]+dp[v][0][0]);
     39 
     40         }else if (m == 3){
     41             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][0]);
     42             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][1]);
     43             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][1]);
     44             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][2]);
     45             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][2]);
     46             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][3]);
     47 
     48             Max(ret, dp[u][0][1]+ai[rt]+dp[v][0][0]);
     49             Max(ret, dp[u][0][1]+ai[rt]+dp[v][1][1]);
     50             Max(ret, dp[u][0][1]+ai[rt]+dp[v][0][1]);
     51             Max(ret, dp[u][0][1]+ai[rt]+dp[v][1][2]);
     52 
     53             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][0]);
     54             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][1]);
     55             Max(ret, dp[u][1][1]+ai[rt]+dp[v][1][1]);
     56             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][2]);
     57             Max(ret, dp[u][1][1]+ai[rt]+dp[v][1][2]);
     58 
     59             Max(ret, dp[u][1][2]+ai[rt]+dp[v][0][0]);
     60             Max(ret, dp[u][1][2]+ai[rt]+dp[v][0][1]);
     61             Max(ret, dp[u][1][2]+ai[rt]+dp[v][1][1]);
     62             
     63             Max(ret, dp[u][1][3]+ai[rt]+dp[v][0][0]);        
     64         }
     65     }else {
     66         if (m == 1){
     67             Max(ret, dp[u][0][0]+ai[rt]);
     68             Max(ret, dp[v][0][0]+ai[rt]);
     69 
     70         }else if (m == 2){
     71             Max(ret, dp[u][0][0]+ai[rt]);
     72             Max(ret,             ai[rt]+dp[v][0][0]);
     73             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][1]);
     74             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][0]);
     75             
     76             Max(ret, dp[u][0][1]+ai[rt]);
     77             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][0]);
     78             
     79         }else if (m == 3){
     80             Max(ret, dp[u][0][0]+ai[rt]);
     81             Max(ret,             ai[rt]+dp[v][0][0]);
     82             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][1]);
     83             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][0]);
     84             Max(ret, dp[u][0][0]+ai[rt]+dp[v][0][1]);
     85             Max(ret, dp[u][0][0]+ai[rt]+dp[v][1][2]);
     86             
     87             Max(ret, dp[u][0][1]+ai[rt]);
     88             Max(ret, dp[u][0][1]+ai[rt]+dp[v][1][1]);
     89             
     90             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][0]);
     91             Max(ret, dp[u][1][1]+ai[rt]+dp[v][0][1]);
     92             Max(ret, dp[u][1][1]+ai[rt]+dp[v][1][1]);
     93             
     94             Max(ret, dp[u][0][2]+ai[rt]);
     95             Max(ret, dp[u][1][2]+ai[rt]+dp[v][0][0]);    
     96         }
     97     }
     98     return ret;
     99 }
    100 void dfs(int rt,int fa){//普通树形DP
    101     if (bi[rt] == 0){
    102         dp[rt][0][0] = ai[rt];
    103     }else {
    104         dp[rt][1][1] = ai[rt];
    105         dp[rt][0][1] = ai[rt];
    106     }
    107     int sz = g[rt].size();
    108     for (int i = 0; i < sz; i++ ){
    109         int c = g[rt][i];
    110         if (c == fa) continue;
    111         dfs(c, rt);
    112         if (bi[rt] == 0){
    113         
    114             Max(dp[rt][0][0] , dp[c][0][0]+ai[rt]);
    115             Max(dp[rt][0][1] , dp[c][0][1]+ai[rt]);
    116             Max(dp[rt][1][1] , dp[c][1][1]+ai[rt]);
    117             Max(dp[rt][0][2] , dp[c][0][2]+ai[rt]);
    118             Max(dp[rt][1][2] , dp[c][1][2]+ai[rt]);
    119             Max(dp[rt][0][3] , dp[c][0][3]+ai[rt]);
    120             Max(dp[rt][1][3] , dp[c][1][3]+ai[rt]);
    121             
    122         }else {
    123             dp[rt][0][0] = 0; 
    124             Max(dp[rt][0][1] , dp[c][0][0]+ai[rt]);
    125             dp[rt][1][1] = ai[rt];
    126             Max(dp[rt][0][2] , dp[c][0][1]+ai[rt]);
    127             Max(dp[rt][1][2] , dp[c][1][1]+ai[rt]);
    128         
    129             Max(dp[rt][0][3] , dp[c][0][2]+ai[rt]);
    130             Max(dp[rt][1][3] , dp[c][1][2]+ai[rt]);
    131         }
    132     }
    133         
    134     for (int i = 0; i < 2; i++){
    135         for (int j = 0; j < m; j++){
    136             Max(ans,dp[rt][i][j]);
    137         }
    138     }
    139     Max(ans,dp[rt][1][m]);
    140     if (bi[rt] == 1) Max(ans,dp[rt][0][m]);//处理出以rt为端点的链
    141     for (int i = 0; i < sz; i++){//合并两条子链得到一条新链
    142         int u = g[rt][i];
    143         for (int j = i+1; j < sz; j++){
    144             int v = g[rt][j];
    145             int t = find(rt,u,v);
    146             Max(ans,t);
    147         }
    148     }
    149 }
    150 void solve(){
    151     ans = 0;
    152     memset(dp,0,sizeof(dp));
    153     dfs(0,-1);
    154     printf("%d
    ",ans);
    155 }
    156 int main(){
    157     int T; scanf("%d",&T);
    158     while (T--){
    159         scanf("%d%d",&n,&m);
    160         for (int i = 0; i < n; i++){
    161             scanf("%d%d",ai+i,bi+i);
    162         }
    163         for (int i = 0; i < n; i++) g[i].clear();
    164         for (int i = 0; i < n-1; i++){
    165             int u,v;
    166             scanf("%d%d",&u,&v);
    167             g[u].push_back(v);
    168             g[v].push_back(u);
    169         }
    170         solve();
    171     }
    172     return 0;
    173 }
    View Code

    hdu 4619

    题意:给你一个棋盘,然后放一些1*2或2*1的棋子,求不覆盖的情况下能放的最多个数;

    分析:把棋盘按照(x+y)%2分成奇偶两类,显然一个棋子不管怎么放都会覆盖到一个奇数格子和偶数格子,

    这样我们就就得到了一个二分图,一边是奇数格子一边是偶数格子,最大匹配就是所求的答案;

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<iostream>
     8 using namespace std;
     9 const int N = 20000+10;
    10 vector<int > g[N];
    11 int n,m;
    12 int vis[N],dy[N];
    13 int find(int u,int tar){
    14     for (int i = 0; i < g[u].size(); i++){
    15         int  c = g[u][i];
    16         if (vis[c] == tar) continue;
    17         vis[c] = tar;
    18         if (dy[c] == -1 || find(dy[c],tar)){
    19             dy[c] = u;
    20             return 1;
    21         }
    22     }
    23     return 0;
    24 }
    25 void solve(){
    26     int ret=0;
    27     memset(dy,-1,sizeof(dy));
    28     memset(vis,0,sizeof(vis));
    29     int cnt= 0;
    30     for (int i = N-1; i >= 0; i--){
    31         if (find(i,++cnt)) ret++;
    32     }
    33     printf("%d
    ",ret);
    34 }
    35 int main(){
    36     while (cin>>n>>m,n+m){
    37         for (int i = 0; i < N; i++) g[i].clear();
    38         for (int i = 0; i < n; i++) {
    39             int x,y; cin>>x>>y;
    40             if ((x+y)%2) g[x*101+y].push_back((x+1)*101+y);
    41             else g[(x+1)*101+y].push_back(x*101+y);
    42         }
    43         for (int i = 0; i < m; i++) {
    44             int x,y; cin>>x>>y;
    45             if ((x+y)%2) g[x*101+y].push_back(x*101+y+1);
    46             else g[x*101+y+1].push_back(x*101+y);
    47         }
    48         solve();
    49     }
    50     return 0;
    51 }
    View Code

    hdu 4612

    题意:n个点m条边的图,问添加一条边使得桥最少;

    分析:先边—双联通缩点(模板),然后变成一棵树,找树上最长路就可以了;

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<cstdlib>
      5 #include<vector>
      6 #include<algorithm>
      7 #include<cmath>
      8 #include<stack>
      9 #pragma comment(linker, "/STACK:1024000000,1024000000") 
     10 #define pbk push_back
     11 using namespace std;
     12 const int N = 200000+10;
     13 
     14 vector<int> G[N],G2[N];
     15 int n,m;
     16 struct e_BCC{
     17     
     18     int n,pre[N],low[N],eccno[N],dfs_clock,ecc_cnt;
     19     stack<int> S;
     20     //vector<int > G;图太大会RE;
     21     void init(int _n){
     22         n = _n;
     23         for (int i = 1; i <= n; i++) G[i].clear();
     24         dfs_clock = ecc_cnt = 0;
     25         memset(eccno,0,sizeof(eccno));
     26         memset(pre,0,sizeof(pre));
     27         while (!S.empty()) S.pop();
     28 
     29     }
     30     void dfs(int u,int fa){
     31         pre[u] = low[u] = ++dfs_clock;
     32         S.push(u);
     33         bool first = 1;
     34         int sz = G[u].size();
     35         for (int i = 0; i < sz; i++){
     36             int  v = G[u][i];
     37             if (v == fa && first){
     38                 first = 0;
     39                 continue;
     40             }
     41             if (!pre[v]){
     42                 dfs(v,u);
     43                 low[u] = min(low[u], low[v]);
     44             }else {
     45                 low[u] = min(low[u], pre[v]);
     46             }
     47         }
     48         if (low[u] == pre[u]){
     49             ecc_cnt++;
     50             while (1){
     51                 int v = S.top(); S.pop();
     52                 eccno[v] = ecc_cnt;
     53                 if (v == u) break;
     54             }
     55         }
     56     }
     57     void find_ecc(){
     58         for (int i = 1; i <= n; i++){
     59             if (!pre[i]) dfs(i,-1);
     60         }
     61     }    
     62 }H;
     63 int vis[N],ans;
     64 int dp[N];
     65 void dfs(int rt){
     66     int m1 = 0, m2 = 0;
     67     dp[rt] = 0;
     68     for (int i = 0; i < G2[rt].size(); i++){
     69         int c = G2[rt][i];
     70         if (vis[c]) continue;
     71         vis[c] = 1;
     72         dfs(c);
     73         
     74         if (m1 == 0) m1 = dp[c]+1;
     75         else if (dp[c]+1>=m1){
     76             if (m2 == 0 || m1>m2) m2 = m1;
     77             m1 = dp[c]+1;
     78         }else if (dp[c]+1>m2) m2 = dp[c]+1;
     79         dp[rt] = max(dp[rt], dp[c] + 1); 
     80     }
     81     
     82     ans = max(ans, m1 + m2);
     83 }
     84 void solve(){
     85     memset(vis,0,sizeof(vis));
     86     ans = 0;
     87     vis[1] = 1;
     88     dfs(1);
     89     printf("%d
    ",H.ecc_cnt-ans-1);
     90 }
     91 int main(){
     92     while (~scanf("%d%d",&n,&m),n+m){
     93         H.init(n);
     94         for (int i = 0; i < m; i++){
     95             int u,v;
     96             scanf("%d%d",&u,&v);
     97             G[u].pbk(v); G[v].pbk(u);
     98         }
     99         H.find_ecc();
    100         for (int i = 0; i <= H.ecc_cnt; i++) G2[i].clear();
    101         for (int i = 1; i <= n; i++){
    102             int u = H.eccno[i];
    103             for (int j = 0; j < G[i].size(); j++){
    104                 int v = H.eccno[G[i][j]];
    105                 G2[u].pbk(v); G2[v].pbk(u);
    106             }
    107         }
    108         solve();
    109     }
    110     return 0;
    111 }
    View Code

    hdu 4620

    题意:告诉你n刀可以切到的水果,和每刀切的时间,并且定义一刀切3个或3个以上为”好刀“,问最多连续的好刀数,并且连续相邻的切刀时间间隔不能超过w;

    分析:暴搜,只要常数小一点就可以水过了,当然可以用十字链表优化搞下,代码是卡过的。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<vector>
     7 #include<cstdlib>
     8 using namespace std;
     9 const int N = 30+10;
    10 bool vis[210];
    11 vector<int > g[N];
    12 int ti[N],id[N];
    13 int n,m,w;
    14 bool cmp(int x,int y){
    15     return ti[x]<ti[y];
    16 }
    17 int ans;
    18 int que[N];
    19 int ap[N];
    20 void dfs(int st,int cnt,int num,int dfs_clock){
    21     if (cnt>ans){
    22         ans = cnt;
    23         memcpy(ap,que,sizeof(que));
    24    }
    25     if (cnt+n-st<ans) return;
    26     for (int i = st+1; i <= n; i++){
    27         if (st != 0  && ti[id[i]]-ti[id[st]]>w) break;
    28         int u = id[i];
    29         int c = 0;
    30         for (int j = 0; j < g[u].size(); j++){
    31             int s = g[u][j];
    32             if (vis[s] == 0){
    33                 vis[s] = u;
    34                 c++;
    35             }
    36         }
    37         if (c>=3){
    38             que[cnt+1] = id[i];
    39             dfs(i,cnt+1,num+c,dfs_clock+1);
    40         }
    41         for (int j = 0; j < g[u].size(); j++){
    42             int s = g[u][j];
    43             if (vis[s] == u){
    44                 vis[s] = 0;
    45             }
    46         }
    47     }
    48 }
    49 void solve(){
    50     memset(vis,0,sizeof(vis));
    51     sort(id+1,id+n+1,cmp);
    52     ans = 0;
    53     dfs(0,0,0,1);
    54     
    55     printf("%d
    ",ans);
    56        sort(ap+1,ap+ans+1); 
    57     for (int i = 1; i < ans; i++){
    58         printf("%d ",ap[i]);
    59     }
    60     printf("%d
    ",ap[ans]);
    61 
    62 }
    63 int main(){
    64     int T; scanf("%d",&T);
    65     while (T--){
    66         scanf("%d%d%d",&n,&m,&w);
    67         for (int i = 1; i <= n; i++) g[i].clear();
    68         for (int i = 1; i <= n; i++){
    69             int c;
    70             id[i] = i;
    71             scanf("%d%d",&c,ti+i);
    72             for (int j = 0; j < c; j++){
    73                 int u; scanf("%d",&u);
    74                 g[i].push_back(u);
    75                 
    76             }
    77         }
    78         solve();
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    团队项目-需求分析报告
    自动化测试框架指南
    一起吐槽接口文档
    居家费拖鞋【FunTester居家日记】
    HTTP接口测试基础【FunTester框架教程】
    Java NIO在接口自动化中应用
    JAVA 可变参数
    HashSet 和 LinkedSet 数据结构
    简单数据结构
    JAVA 迭代器的简单使用
  • 原文地址:https://www.cnblogs.com/Rlemon/p/3215491.html
Copyright © 2011-2022 走看看