2013 Multi-University Training Contest 8 小结

        前天做多校,做的很差,一直都是没怎么认真想题就去做或者就是感觉一看是树形dp就觉得很难,然后就没有认真去分析,心里感觉那样的题我肯定也写不出来,但是今天真的心平气和的做的时候发现也不难。。。。

         想起来多校的第五场,有一道kmp的变形题,我分析了一半,然后和强神又分析了下,其实思路就和题解上是一样的了,但是却没有写:第一:感觉不好写,不知道怎么去写,写了也不一定可以写出来,第二:那题过的也就是那几个队,如果我们分析出来的话那些大牛学校也应该分析出来了,所以应该是错的吧,所以分析了那么多程序却是一个字都没有写的。比赛结束后我还在找这方面那方面的原因,最后强神说的一句话我觉得很好,就是没有自信,不敢去写,怕写错,不相信自己!!!!!

         前天比赛,我做了第六题,不知道当时激动什么,连最基本的打表都忘了,想着那么多学校都过了,应该就可以暴力的,结果来了一个一点弯都没有拐的暴力,果断的TLE了,第四题的树形dp,也有点思路,但是没有深入去分析,一直觉得树形dp可难(心里作用),而且想着这些题钢牛是强项,也不用我去写,然后就没有然后了。。。第十题,最大二分匹配又加了点条件,想到的是建图然后求强连通分量,但是思路不怎么成熟,没有想到去虚拟王子和公主,然后就直接求联通分量了,然后就是自己找数据的时候发现了各种bug,然后一直WA,到最后就只想到了求强连通分量的思路可能是错的,没有进一步在此基础上去深入,贡献了无数的wa啊!第三题是博弈题,我一看了一眼图就让强神去看了,我的博弈真的是差,到现在都一道博弈题靠自己的力量写出来的都没有,然后强神奋战了几乎一下午,贡献了无数的RE和WA,也没有过,然后后来看了题解,他说他都分析出来了,只是什么与写错了。。。钢牛整场都在奋战第九题,方神回家了,然后整场比赛的结果,唉,说多了都是泪啊!

      暑假过的好快,集训也快要结束了,然后感觉整个刷题的过程学东西可慢了,但是还是学会了不少,我感觉应该在比赛中多多总结经验,不然比赛因为一时失误将会做的题没做出来,那就亏大了啊!

     今天将前天比赛的我集中分析的三道题写了一遍,感觉自己分析的思路总是差了那么一点点,然后就是过不去,我想什么时候给那个一点点给过去了,那应该是很大的提高吧! 还有一点就是平时训练的时候很懒散,算法想出来的时候但是写的时候总是晃晃悠悠的,没有一点时间观念,然后就导致比赛写题的时候敲代码花了好长时间,一定要改啊!

    然后的然后,将我写的三道题代码贴出来好了,还有一道自己度错题WA了n次啊!!!!O_O

hdoj 4679

/////////////////////////////////////////////////////////////////////////
// File Name: 4679.cpp
// Author: wang
// mail: 
// Created Time: 2013-8-17 14:55:24
/////////////////////////////////////////////////////////////////////////
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cmath>

#include <algorithm>
#include<iostream>
#include<queue>
#include <map>
using namespace std; typedef long long ll;
#define INF (INT_MAX/10)
#define SQR(x) ((x)*(x))
#define rep(i, n) for (int i=0; i<(n); ++i)
#define repf(i, a, b) for (int i=(a); i<=(b); ++i)
#define repd(i, a, b) for (int i=(a); i>=(b); --i)
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define N 210000
 int h[N],f[N];//h[y]指的是子树中的最大直径的
int pre[N]; int n,len; int dis[N]; int Max,sign; struct node{ int y,w,pre,sign; };
node a[N]; int fir[N][3]; int firp[N][3];//最大,次大和次大大
 void init() {
    memset(pre,-1,sizeof(pre));
    len=1;
    memset(h,0,sizeof(h));
    memset(f,0,sizeof(f));
    memset(fir,0,sizeof(fir));
    memset(firp,-1,sizeof(firp));
    memset(dis,0,sizeof(dis)); } void addpage(int x,int y,int w,int z) {
    a[len].sign=z;
    a[len].y=y;
    a[len].w=w;
    a[len].pre=pre[x];
    pre[x]=len++; } void dfs(int x,int fa)//最大的肯定得有的
{ for(int i=pre[x]; i!=-1; i=a[i].pre) { int y=a[i].y; if(y==fa) continue;
        dfs(y,x); //从上面下来的 
        rep(j,3)//更新的
 if(fir[y][0]+a[i].w>fir[x][j]) {
                repd(k,2,j+1)//-1也是这样传递的
                    fir[x][k]=fir[x][k-1],
                    firp[x][k]=firp[x][k-1];
                fir[x][j]=fir[y][0]+1;//y的最大的子跟+1;
                firp[x][j]=y; break; } }
    h[x]=fir[x][0]+fir[x][1];//指的是最大的
} void ddfs(int x,int fa) { 
    //fa的dis怎么维护的????
 for(int i=pre[x]; i!=-1; i=a[i].pre) { int y=a[i].y;//删除以y为跟的子树的
 if(y==fa) continue; int m=0;
        rep(j,3)//x子树中另外的最大的,
 { if(firp[x][j]!=y) {
                f[y]+=fir[x][j],m++;
                dis[y]=max(dis[y],fir[x][j]+1);//求出y以上的最大值的
 } if(m==2) break; }
        dis[y]=max(dis[y],dis[x]+1);//有可能是上面的承接下来的
       rep(j,3) if(firp[x][j]!=y) {
             f[y]=max(f[y],fir[x][j]+dis[x]); break; }     
        //x中的最大的
        f[y]=max(f[y],f[x]);//去掉x时的最大的
 for(int k=pre[x]; k!=-1; k=a[k].pre)//x的其它子节点中的最大的
 { if(a[k].y!=fa && a[k].y!=y) {
                f[y]=max(f[y],h[a[k].y]);//兄弟子树中的最大值的
 } }
        ddfs(y,x); } } void ans(int x,int fa) { for(int i=pre[x]; i!=-1; i=a[i].pre) { int y=a[i].y; if(y==fa) continue; int m=a[i].w*max(h[y],f[y]); if(m<Max) {
            Max=m;
            sign=a[i].sign; } else if(m==Max && a[i].sign<sign)
            sign=a[i].sign;
        ans(y,x); } } int main() { int test;
    scanf("%d",&test); int x,y,z;
    repf(ror,1,test) {
        init();
        scanf("%d",&n);
        rep(i,n-1) {
            scanf("%d%d%d",&x,&y,&z);
            addpage(x,y,z,i+1);
            addpage(y,x,z,i+1); }
        dfs(1,-1);//求出x为跟的子树中的最大的直径的
        //去掉以x为跟的子树后的最大直径f[N];
        f[1]=0; 
        dis[1]=0;
        ddfs(1,-1);//默认1为整棵树的跟的
//        repf(i,1,n) cout<<h[i]<<" "; cout<<endl;
//        repf(i,1,n) cout<<f[i]<<" "; cout<<endl;
//        repf(i,1,n) cout<<dis[i]<<" "; cout<<endl;
        Max=INT_MAX;
        ans(1,-1);
        printf("Case #%d: %d\n",ror,sign); } return 0; }

 

hdoj  4681 

String

/////////////////////////////////////////////////////////////////////////
// File Name: t.cpp
// Author: wang
// mail: 
// Created Time: 2013-8-15 12:38:36
/////////////////////////////////////////////////////////////////////////
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cmath>

#include <algorithm>
#include<iostream>
#include<queue>
#include <map>
using namespace std; typedef long long ll;
#define INF (INT_MAX/10)
#define SQR(x) ((x)*(x))
#define rep(i, n) for (int i=0; i<(n); ++i)
#define repf(i, a, b) for (int i=(a); i<=(b); ++i)
#define repd(i, a, b) for (int i=(a); i>=(b); --i)
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define N 1010
char a[N],b[N],c[N]; int dp[N][N]; int dp2[N][N]; int n,m; struct node{ int l,r; };
node aa[N*10],bb[N*10]; void fun() {
    n=0; int lena=strlen(a),len=strlen(c);
    rep(i,lena) { if(a[i]==c[0]) {
            aa[n].l=i; int     k=0;
            repf(j,i,lena-1) { if(a[j]==c[k]) {
                    k++; if(k==len) {
                        aa[n++].r=j; break; } } } } } return ; } void fun1() {
    m=0; int lenb=strlen(b),len=strlen(c);
    rep(i,lenb) { if(b[i]==c[0]) {
            bb[m].l=i; int k=0;
            repf(j,i,lenb-1) { if(b[j]==c[k]) {
                    k++; if(k==len) {
                        bb[m++].r=j; break; } } } } } return ; } void work() {
    memset(dp,0,sizeof(dp)); int lena=strlen(a),lenb=strlen(b);
    rep(i,lena)
        rep(j,lenb) if(a[i]==b[j])
             dp[i+1][j+1]=max(dp[i][j]+1,max(dp[i+1][j],dp[i][j+1])); else
             dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
//    rep(i,lena+1){
//        rep(j,lenb+1)
//            cout<<dp[i][j]<<" "; cout<<endl;}cout<<endl;
    memset(dp2,0,sizeof(dp2));
    repd(i,lena-1,0)
        repd(j,lenb-1,0) if(a[i]==b[j])
            dp2[i][j]=dp2[i+1][j+1]+1; else dp2[i][j]=max(dp2[i+1][j],dp2[i][j+1]);
//    repd(i,lena-1,0){
//        repd(j,lenb-1,0)
//            cout<<dp2[i][j]<<" "; cout<<endl;}
} int main() { int test;
    scanf("%d",&test);
    getchar();
    repf(ror,1,test) {
       // scanf("%s%s%s",a,b,c); 
        gets(a); gets(b); gets(c);
        fun();
        fun1(); int Max=0;
        work(); int lena=strlen(a); int lenb=strlen(b);
//        cout<<n<<" "<<m<<endl;
        rep(i,n)
            rep(j,m) {
//                cout<<aa[i].l<<" "<<aa[i].r<<" "<<bb[j].l<<" "<<bb[j].r<<endl;
//                cout<<dp[aa[i].l][bb[j].l]<<" "<<dp[lena][lenb]<<" "<<dp[aa[i].r+1][bb[j].r+1]<<endl;
              Max=max(Max,dp[aa[i].l][bb[j].l]+dp2[aa[i].r+1][bb[j].r+1]); }
        printf("Case #%d: %d\n",ror,Max+strlen(c)); } return 0; }
1010

Prince and Princess

/////////////////////////////////////////////////////////////////////////
// File Name: 4685.cpp
// Author: wang
// mail:
// Created Time: 2013-8-17 10:18:33
/////////////////////////////////////////////////////////////////////////
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cmath>

#include <algorithm>
#include<iostream>
#include<queue>
#include <map>
using namespace std;
typedef
long long
ll;
#define INF (INT_MAX/10)
#define SQR(x) ((x)*(x))
#define rep(i, n) for (int i=0; i<(n); ++i)
#define repf(i, a, b) for (int i=(a); i<=(b); ++i)
#define repd(i, a, b) for (int i=(a); i>=(b); --i)
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define N 2005//增加公主或者王子的饿个数可以很大的
int n,m;
bool
vis[N];
int
ans[N];

class
ring{
    public
:
    int
len,tot,ror,col;
    int
dfn[N],low[N],pre[N];
    int
stage[N];
    bool
mark[N];
    int
Stack[N];
    struct
node{
        int
y,pre;
    };

    node a[N*1001];
    void
init()
    {

        len=1; col=0; tot=1; ror=1;
        memset(dfn,0,sizeof(dfn));
        memset(pre,-1,sizeof(pre));
        memset(mark,false,sizeof(mark));
        memset(stage,0,sizeof(stage));
    }

    void
addpage(int s,int t)
    {

//        cout<<s<<" "<<t<<endl;
        a[len].y=t;
        a[len].pre=pre[s];
        pre[s]=len++;
    }

    void
dfs(int x)
    {

       Stack[ror++]=x;
       dfn[x]=low[x]=tot++;
       mark[x]=true;
       for
(int
i=pre[x]; i!=-1; i=a[i].pre)
       {

          int
y=a[i].y;
          if
(!
dfn[y])
          {

             dfs(y);
             low[x]=min(low[x],low[y]);
          }
else if(
mark[y]==true)
             low[x]=min(low[x],dfn[y]);
        }

        int
i;
        if
(
dfn[x]==low[x])
        {
           ++
col;
           do
{

               i=Stack[--ror];
               mark[i]=false;
               stage[i]=col
            }
while(
i!=x);
        }
}   
};

ring ri;
class
match{
    public
:

    vector<int>vec[N];
    bool
vis[N];
    int
n,k;
    int
next[N];
    void
init()
    {

        rep(i,N) vec[i].clear();//清空的
        memset(next,-1,sizeof(next));
    }

    bool
find(int t)
    {

        rep(i,vec[t].size())
        {

            int
m=vec[t][i];
            if
(
vis[m]==false)
            {

                vis[m]=true;
                if
(
next[m]==-1 || find(next[m]))
                {

                    next[m]=t;
                    return
true;
                }
            }
        }

        return
false;
    }

    int
sum()//求的是最大匹配数的
    {
        int
m=0;
        rep(i,n)
        {

            memset(vis,false,sizeof(vis));
            if
(
find(i))
                m++;
        }

        return
m;
    }
};

match ma;

void
solve()
{

    int
l,x;
    ma.n=n;
    ma.init();
    rep(i,n)
    {

       scanf("%d",&l);
       while
(
l--)
           scanf("%d",&x),ma.vec[i].push_back(x-1);//减去1的
    }
    ma.sum();//最大匹配的
    memset(vis,false,sizeof(vis));
    rep(i,m)//m个公主的
        if(ma.next[i]==-1)//没有匹配的
        {//增加一个王子的
            ma.next[i]=n;
        //    ma.vec[n].clear();//增加之前先清空的
            rep(j,m) ma.vec[n].push_back(j);//王子喜爱每一位公主的
            vis[n]=true;
            n++;
        }

        else
vis[ma.next[i]]=true;
    rep(i,n)
        if
(
vis[i]==false)//该王子没有被匹配的
        {//增加一位公主的
             ma.next[m]=i;//增加一位公主的
             rep(j,n) ma.vec[j].push_back(m);//每位王子都爱这个公主的
             m++;
        }
}

void
work()
{

     ri.init();
     rep(i,n)
         rep(j,ma.vec[i].size())
            ri.addpage(i,ma.vec[i][j]+n);//加边的
     rep(i,m)
         ri.addpage(i+n,ma.next[i]);
     rep(i,n+m)
         if
(
ri.dfn[i]==0)  ri.dfs(i);//求强连通的
}
int
main()
{

    int
test;
    scanf("%d",&test);
    int
nn,mm;
    repf(ror,1,test)
    {

        scanf("%d%d",&n,&m);
        nn=n; mm=m;
        solve();//最大匹配并进行添加的
        work();//求强连通分量的额
//        rep(i,n+m) cout<<ri.stage[i]<<endl;
        printf("Case #%d:\n",ror);
        rep(i,nn)
        {

            ans[0]=0;
            for
(int
j=ri.pre[i]; j!=-1; j=ri.a[j].pre)//可以匹配的
            {
                int
y=ri.a[j].y-n;
                if
(
y<mm && ri.stage[i]==ri.stage[y+n])
                    ans[++ans[0]]=y;
            }

            printf("%d",ans[0]);
            sort(ans+1,ans+1+ans[0]);
            repf(j,1,ans[0])
                printf(" %d",ans[j]+1);
            printf("\n");
        }
    }

    return
0;
}



 

你可能感兴趣的:(2013 Multi-University Training Contest 8 小结)