臨時代碼儲存

https://www.luogu.org/problem/show?pid=3386
二分圖模版題……debug真累

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1001;
int n,m,e;
bool vis[maxn],a[maxn][maxn]={0};//u,v
int shu[maxn]={0};//判斷m中點與n中何點連接 
bool dfs(int i){
    for(int j=1;j<=m;j++){
        if(a[i][j]&&!vis[j]){
            vis[j]=1;
            if(!shu[j]||dfs(shu[j])){
                shu[j]=i;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    int u,v,ans=0;
    scanf("%d%d%d",&n,&m,&e);
    for(int i=1;i<=e;i++){
        scanf("%d%d",&u,&v);
        if(u>n||v>m) continue;
        a[u][v]=1;
    }
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        if(dfs(i))ans++;
    }
    printf("%d",ans);
    return 0;
}

順便攢一道題
hdu 3036
未完成

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=10000;
const int INF=2147483640;
struct{
    int next;
    int to;
    int w;
}edge[1000000];
int head[maxn],cnt=-1;
void add(int u,int v,int w){//u起點v終點w容量 
    cnt++;
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
int lev[maxn],cur[maxn];//lev層數,cur[i]爲以i爲起點的邊的編號 
bool bfs(int m){//強制1爲源點,m爲匯點 
    int dui[m],r=0;//隊列和右指針 
    for(int i=1;i<=m;i++){//初始化 
        lev[i]=-1;
        cur[i]=head[i];
    }
    dui[0]=1,lev[1]=0;
    int u,v;//u起點v終點 
    for(int l=0;l<=r;l++){//左指針 
        u=dui[l];
        for(int e=head[u];e!=-1;e=edge[e].next){
            v=edge[e].to;
            if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分層 
                lev[v]=lev[u]+1;
                r++;
                dui[r]=v;//v入隊 
                if(v==m)return 1;//分層完畢 
            }
        }
    }
    return 0;//無法分層 
}
int dinic(int u,int flow,int m){//u當前點,flow爲下面的點能夠分配多大的流量,m終點 
    if(u==m)return flow;//終點直接全流入
    int res=0,delta;//res實際流量 
    for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相當於cur[u]=e;即流滿的邊不會再被掃一次 
        int v=edge[e].to;
        if(edge[e].w>0&&lev[u]<lev[v]){//只能從低層往高層流 
            delta=dinic(v,min(edge[e].w,flow-res),m); 
            if(delta>0){//如果增廣 
                edge[e].w-=delta;//正向邊容量減少 
                edge[e^1].w+=delta;//反向邊仍量增加(暗示退流) 
                res+=delta;//擴張流量增加 
                if(res==flow)break;//可流的都流完了,及時跳出 
            }
        }
    }
    if(res!=flow)lev[u]=-1;//沒流完,說明以後不能從這個點流出任何流量,那就不需要這個點了 
    return res;
}
char a[14][14];
int vis[14][14],dis[14][14];
void BFS(int x,int y){
    int x1[160],y1[160];
    int r=0;
    x1[0]=x;y1[0]=y;dis[x][y]=0;
    for(int l=0;l<=r;l++){
        int t1=x1[l],t2=y1[l];
        if(a[t1+1][t2]!='X'&&vis[t1+1][t2]==0){
            r++;
            x1[r]=t1+1;y1[r]=t2;
            vis[t1+1][t2]=1;
            dis[t1+1][t2]=min(dis[t1+1][t2],dis[t1][t2]+1);
        }
        if(a[t1-1][t2]!='X'&&vis[t1-1][t2]==0){
            r++;
            x1[r]=t1-1;y1[r]=t2;
            vis[t1-1][t2]=1;
            dis[t1-1][t2]=min(dis[t1-1][t2],dis[t1][t2]+1);
        }
        if(a[t1][t2+1]!='X'&&vis[t1][t2+1]==0){
            r++;
            x1[r]=t1;y1[r]=t2+1;
            vis[t1][t2+1]=1;
            dis[t1][t2+1]=min(dis[t1][t2+1],dis[t1][t2]+1);
        }
        if(a[t1][t2-1]!='X'&&vis[t1][t2-1]==0){
            r++;
            x1[r]=t1;y1[r]=t2-1;
            vis[t1][t2-1]=1;
            dis[t1][t2-1]=min(dis[t1][t2-1],dis[t1][t2]+1);
        }
    }
    return;
}
int id[14][14];
int rdis[14][14][144]={0};
int main(){
    int r,c,t;
    int sumH=0,sumE=0;
    scanf("%d%d%d\n",&r,&c,&t);
    for(int i=1;i<=r;i++){
        for(int j=1;j<=c+1;j++){
            scanf("%c",a[i][j]);
            if(a[i][j]=='.'){
                sumH++;
                id[i][j]=sumH;
            }
            if(a[i][j]=='E'){
                sumE++;
                id[i][j]=sumE;
            }
        }
    }
    for(int i=1;i<=r;i++){
        a[i][0]='X';a[i][c+1]='X';
    }
    for(int j=1;j<=c;j++){
        a[0][j]='X';a[r+1][j]='X';
    }
    for(int i=1;i<=r;i++){
        for(int j=1;j<=c;j++){
            if(a[i][j]=='E'){
                memset(vis,0,sizeof(vis));
                for(int k=1;k<=r;k++){
                    for(int l=1;l<=c;l++){
                        dis[k][l]=INF-1;
                    }
                }
                BFS(i,j);
                for(int k=1;k<=r;k++){
                    for(int l=1;l<=c;l++){
                        if(a[k][l]=='.'){
                            rdis[k][l][id[i][j]]=dis[k][l]; 
                        }
                    }
                }
            }
        }
    }
    for(int i=1;i<=t+sum+2;i++){
        head[i]=-1;
    }
    for(int i=1;i<=n;i++){
        int s,e,c;
        scanf("%d%d%d",&s,&e,&c);
        add(s,e,c);
        add(e,s,0);
    }
    int ans=0;
    while(bfs(m)==1)ans+=dinic(1,INF,m);
    printf("%d",ans);
    return 0;
}

http://codevs.cn/problem/1993/
草地排水,網絡流dinic板子

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=201;
const int INF=2147483640;
struct{
    int next;
    int to;
    int w;
}edge[2*maxn];
int head[2*maxn],cnt=-1;
void add(int u,int v,int w){//u起點v終點w容量 
    cnt++;
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
int lev[maxn],cur[maxn];//lev層數,cur[i]爲以i爲起點的邊的編號 
bool bfs(int m){//強制1爲源點,m爲匯點 
    int dui[m],r=0;//隊列和右指針 
    for(int i=1;i<=m;i++){//初始化 
        lev[i]=-1;
        cur[i]=head[i];
    }
    dui[0]=1,lev[1]=0;
    int u,v;//u起點v終點 
    for(int l=0;l<=r;l++){//左指針 
        u=dui[l];
        for(int e=head[u];e!=-1;e=edge[e].next){
            v=edge[e].to;
            if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分層 
                lev[v]=lev[u]+1;
                r++;
                dui[r]=v;//v入隊 
                if(v==m)return 1;//分層完畢 
            }
        }
    }
    return 0;//無法分層 
}
int dinic(int u,int flow,int m){//u當前點,flow爲下面的點能夠分配多大的流量,m終點 
    if(u==m)return flow;//終點直接全流入
    int res=0,delta;//res實際流量 
    for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相當於cur[u]=e;即流滿的邊不會再被掃一次 
        int v=edge[e].to;
        if(edge[e].w>0&&lev[u]<lev[v]){//只能從低層往高層流 
            delta=dinic(v,min(edge[e].w,flow-res),m); 
            if(delta>0){//如果增廣 
                edge[e].w-=delta;//正向邊容量減少 
                edge[e^1].w+=delta;//反向邊仍量增加(暗示退流) 
                res+=delta;//擴張流量增加 
                if(res==flow)break;//可流的都流完了,及時跳出 
            }
        }
    }
    if(res!=flow)lev[u]=-1;//沒流完,說明以後不能從這個點流出任何流量,那就不需要這個點了 
    return res;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        head[i]=-1;
    }
    for(int i=1;i<=n;i++){
        int s,e,c;
        scanf("%d%d%d",&s,&e,&c);
        add(s,e,c);
        add(e,s,0);
    }
    int ans=0;
    while(bfs(m)==1)ans+=dinic(1,INF,m);
    printf("%d",ans);
    return 0;
}

【題目描述】
給出一張n*n(n<=100)的國際象棋棋盤,其中被刪除了一些點,問可以使用多少1*2的多米諾骨牌進行掩蓋。
【輸入格式】
第一行爲n,m(表示有m個刪除的格子)
第二行到m+1行爲x,y,分別表示刪除格子所在的位置
【輸出格式】
一個數,即最大覆蓋格數
【樣例輸入】
8 0
【樣例輸出】
32

想象真的國際象棋棋盤,黑色的一幫,白色的一幫,黑白相鄰的那麼從黑連向白的,變成二分圖匹配。

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=102;
int n,m,e;
bool vis[maxn][maxn],a[maxn][maxn][maxn][maxn]={0};//u,v
int shu[maxn][maxn][2]={0};//判斷m中點與n中何點連接 
bool dfs(int i,int j){
    for(int k=-1;k<=1;k++){
        for(int l=-1;l<=1;l++){
            if(k==l||k+l==0)continue;
            if(i+k==0||j+l==0||i+k==n+1||j+l==n+1)continue;
            if(a[i][j][i+k][j+l]&&!vis[i+k][j+l]){
                vis[i+k][j+l]=1;
                if((!shu[i+k][j+l][0]&&!shu[i+k][j+l][1])||dfs(shu[i+k][j+l][0],shu[i+k][j+l][1])){
                    shu[i+k][j+l][0]=i;
                    shu[i+k][j+l][1]=j;
                    return 1;
                }
            }
        }
    }
    return 0;
}
int main(){
    int u,v,ans=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i%2==j%2){
                a[i][j][i-1][j]=a[i][j][i+1][j]=a[i][j][i][j-1]=a[i][j][i][j+1]=1;
            }
        }
    }
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        if(x%2==y%2){
            a[x][y][x-1][y]=a[x][y][x+1][y]=a[x][y][x][y-1]=a[x][y][x][y+1]=0;
        }else{
            a[x-1][y][x][y]=a[x+1][y][x][y]=a[x][y-1][x][y]=a[x][y+1][x][y]=0;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            memset(vis,0,sizeof(vis));
            if(dfs(i,j))ans++;
        }
    }
    printf("%d",ans);
    return 0;
}

codevs1789:最大獲利
http://codevs.cn/problem/1789/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=55010;
const int INF=2147483640;
struct{
    int next;
    int to;
    int w;
}edge[6666666];//隨便打的不然maxn的平方會爆空間
int head[maxn],cnt=-1;
void add(int u,int v,int w){//u起點v終點w容量 
    cnt++;
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
}
int lev[maxn],cur[maxn];//lev層數,cur[i]爲以i爲起點的邊的編號 
bool bfs(int n,int m,int zong){//n爲源點,m爲匯點,zong爲個數 
    int dui[zong+1],r=0;//隊列和右指針 
    for(int i=1;i<=zong;i++){//初始化 
        lev[i]=-1;
        cur[i]=head[i];
    }
    dui[0]=n,lev[n]=0;
    int u,v;//u起點v終點 
    for(int l=0;l<=r;l++){//左指針 
        u=dui[l];
        for(int e=head[u];e!=-1;e=edge[e].next){
            v=edge[e].to;
            if(edge[e].w>0&&lev[v]==-1){//1.能走 2.未分層 
                lev[v]=lev[u]+1;
                r++;
                dui[r]=v;//v入隊 
                if(v==m)return 1;//分層完畢 
            }
        }
    }
    return 0;//無法分層 
}
int dinic(int u,int flow,int m){//u當前點,flow爲下面的點能夠分配多大的流量,m終點 
    if(u==m)return flow;//終點直接全流入
    int res=0,delta;//res實際流量 
    for(int &e=cur[u];e!=-1;e=edge[e].next){//'&'相當於cur[u]=e;即流滿的邊不會再被掃一次 
        int v=edge[e].to;
        if(edge[e].w>0&&lev[u]<lev[v]){//只能從低層往高層流 
            delta=dinic(v,min(edge[e].w,flow-res),m); 
            if(delta>0){//如果增廣 
                edge[e].w-=delta;//正向邊容量減少 
                edge[e^1].w+=delta;//反向邊仍量增加(暗示退流) 
                res+=delta;//擴張流量增加 
                if(res==flow)break;//可流的都流完了,及時跳出 
            }
        }
    }
    if(res!=flow)lev[u]=-1;//沒流完,說明以後不能從這個點流出任何流量,那就不需要這個點了 
    return res;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+m+2;i++){
        head[i]=-1;
    }
    for(int i=1;i<=n;i++){
        int s;
        scanf("%d",&s);
        add(i,n+m+2,s);
        add(n+m+2,i,0);
    }
    int sum=0;
    for(int j=n+1;j<=n+m;j++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(j,a,INF);add(a,j,0);
        add(j,b,INF);add(b,j,0);
        add(n+m+1,j,c);add(j,n+m+1,0);
        sum+=c;
    }
    int ans=0;
    while(bfs(n+m+1,n+m+2,n+m+2)==1)ans+=dinic(n+m+1,INF,n+m+2);
    printf("%d",sum-ans);
    return 0;
}

codevs 1163訪問藝術館
http://codevs.cn/problem/1163/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int tree[201][601];
int dis[201][201];
int t;
const int INF=214748364;
int hua[201]={0};
int sum=0;
void read(int fa,int i){
    scanf("%d",&dis[fa][i]);
    int ha;
    scanf("%d",&ha);
    if(ha==0){
        read(i,i*2);
        read(i,i*2+1);
        hua[i]=hua[i*2+1]+hua[i*2];
        for(int j=0;j<=hua[i];j++){
            for(int k=0;k<=j;k++){
                int f=0;
                if(k!=0)f+=dis[i][i*2]*2;
                if(j-k!=0)f+=dis[i][i*2+1]*2;
                tree[i][j]=min(tree[i][j],tree[i*2][k]+tree[i*2+1][j-k]+f);
            }
        }
    }else{
        hua[i]=ha;
        sum+=ha;
        for(int j=0;j<=ha;j++){
            tree[i][j]=j*5;
        }
    }
    return;
}
int main(){
    scanf("%d",&t);
    for(int i=0;i<=200;i++){
        tree[i][0]=0;
        for(int j=1;j<=600;j++){
            tree[i][j]=INF;
        }
    }
    read(1,2);
    for(int i=sum;i>=0;i--){
        if(tree[2][i]+dis[1][2]*2<=t){
            printf("%d",i);
            return 0;
        }
    }
    return 0;
}

1201: 泥濘的牧場
時間限制: 1 Sec 內存限制: 128 MB
提交: 78 解決: 30
[提交][狀態][討論版]
題目描述
大雨侵襲了奶牛們的牧場.牧場是一個R * C的矩形,其中1≤R,C≤50.大雨將沒有長草的土地弄得泥濘不堪,可是小心的奶牛們不想在喫草的時候弄髒她們的蹄子.

爲了防止她們的蹄子被弄髒,約翰決定在泥濘的牧場裏放置一些木板.每一塊木板的寬度爲1個單位,長度任意.每一個板必須放置在平行於牧場的泥地裏.

約翰想使用最少的木板覆蓋所有的泥地.一個木板可以重疊在另一個木板上,但是不能放在草地上.

輸入
第1行:兩個整數R和C.

第2到R+1行:每行C個字符,其中“*’代表泥地,“.”代表草地.

輸出
最少需要多少木板.

樣例輸入
4 4
..
.*
*.
..*.
樣例輸出
4
提示
樣例說明:

木板的放置方法如下:


1.2.

.333

444.

..2.

木板2和3、4重疊

每個點可以橫着板子來與豎着板子來。
那就橫着豎着點連一條線,然後要求所有線都能夠到
那就是最小點覆蓋了+-+

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1000;
int n,m;
char s[maxn][maxn]={0};
int c[maxn][maxn]={0},d[maxn][maxn]={0};
bool vis[maxn],a[maxn][maxn]={0};//u,v
int shu[maxn]={0};//判斷m中點與n中何點連接 
bool dfs(int i,int o){
    for(int j=1;j<=o;j++){
        if(a[i][j]&&!vis[j]){
            vis[j]=1;
            if(!shu[j]||dfs(shu[j],o)){
                shu[j]=i;
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    int u,v,ans=0;
    int x1=0,y1=0;
    scanf("%d%d\n",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m+1;j++){
            scanf("%c",&s[i][j]);
            if(j==m+1)continue;
            if(s[i][j]=='*'){
                if(j>1&&s[i][j-1]=='*')c[i][j]=c[i][j-1];
                else{
                    x1++;
                    c[i][j]=x1;
                }
                if(i>1&&s[i-1][j]=='*')d[i][j]=d[i-1][j];
                else{
                    y1++;
                    d[i][j]=y1;
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(s[i][j]=='*')
            a[c[i][j]][d[i][j]]=1;
        }
    }
    int k=x1;
    for(int i=1;i<=k;i++){
        memset(vis,0,sizeof(vis));
        if(dfs(i,y1))ans++;
    }
    printf("%d",ans);
    return 0;
}

自學KMP
然而
https://www.luogu.org/problem/show?pid=3375
雖然是板子題。
但特別不推薦寫。
可能會出現:
1.cincout卡時間
2.gets函數做答案是對的但是就是不給過//深受此毒害的路由器

#include<cstdio>
#include<cstring>
using namespace std;
char s1[1000001];
char s2[1001];
int nxt[1001]={0};
void getnext(int m){//處理nxt數組
    //原理:自己匹配自己 
    int j=0;
    for(int i=2;i<=m;i++){
        while(j!=0&&s2[j+1]!=s2[i])j=nxt[j];//無法匹配時移動字符串使之能匹配 
        if(s2[j+1]==s2[i])j++;
        nxt[i]=j;//對應匹配的位置(同時也是匹配的長度) 
    }
    return;
}
void KMP(int n,int m){//KMP
    int j=0;
    for(int i=1;i<=n;i++){
        while(j!=0&&s2[j+1]!=s1[i])j=nxt[j];//同上 
        if(s2[j+1]==s1[i])j++;
        if(j==m){//同上 
            printf("%d\n",i-j+1);
            j=nxt[j];//繼續查找 
        }
    }
    return;
}
int main(){
    scanf("%s%s",s1+1,s2+1);
    //雖然可以從0開始讀入字符串
    //但是懶
    int n=strlen(s1+1),m=strlen(s2+1);
    //相應的字符串長度改一下 
    getnext(m);
    KMP(n,m);
    for(int i=1;i<=m;i++){
        printf("%d ",nxt[i]);
    }
    return 0;
}

下面兩道是AC自動機模版題
都挺坑的。
十分感謝上面題解的第一位仁兄。
我把他的模版復刻了一遍才過。
另外我才知道用string讀字符串要方便。
並且直接用字符串還會更快(這什麼原理?!)
總之AC自動機這個黑科技我還沒會透。
就這樣吧。
https://www.luogu.org/problem/show?pid=3808

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
struct trie{
    int ed;
    int a[26];
    int fail;
}tree[1000000]={0};
int cnt=0;
inline void insert(string s){
    int now=0;
    int len=s.length();
    for(int i=0;i<len;i++){
        int t=s[i]-97;
        if(tree[now].a[t]==0){
            cnt++;
            tree[now].a[t]=cnt;
        }
        now=tree[now].a[t];
    }
    tree[now].ed++;
    return;
}
void getfail(){
    queue<int>q;
    tree[0].fail=0;
    //以下是對第一層的特殊處理 
    for(int i=0;i<26;i++){
        if(tree[0].a[i]!=0){
            tree[tree[0].a[i]].fail=0;
            q.push(tree[0].a[i]);
        }
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(tree[u].a[i]!=0){
                tree[tree[u].a[i]].fail=tree[tree[u].fail].a[i];
                q.push(tree[u].a[i]);
            }else{
                tree[u].a[i]=tree[tree[u].fail].a[i];
            }
        }
    }
    return;
}
int check(string s){
    int now=0,ans=0;
    int len=s.length();
    for(int i=0;i<len;i++){
        int t=s[i]-97;
        now=tree[now].a[t];
        for(int j=now;j&&tree[j].ed!=-1;j=tree[j].fail){
            ans+=tree[j].ed;
            tree[j].ed=-1;
        }
    }
    return ans;
}
int main(){
    int n;
    string s;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s;
        insert(s);
    }
    getfail();
    cin>>s;
    cout<<check(s);
    return 0;
}

https://www.luogu.org/problem/show?pid=3796

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
struct trie{
    int ed;
    int a[26];
    int fail;
}tree[100000]={0};
struct remember{
    int cont;
    int i;
}re[100000]={0};
string s[100000];
bool cmp(remember a,remember b){
    if(a.cont!=b.cont)
    return a.cont>b.cont;
    else
    return a.i<b.i;
}
int cnt=0;
inline void insert(string s,int num){
    int now=0;
    int len=s.length();
    for(int i=0;i<len;i++){
        int t=s[i]-97;
        if(tree[now].a[t]==0){
            cnt++;
            tree[now].a[t]=cnt;
        }
        now=tree[now].a[t];
    }
    tree[now].ed=num;
    return;
}
void getfail(){
    queue<int>q;
    tree[0].fail=0;
    //以下是對第一層的特殊處理 
    for(int i=0;i<26;i++){
        if(tree[0].a[i]!=0){
            tree[tree[0].a[i]].fail=0;
            q.push(tree[0].a[i]);
        }
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(tree[u].a[i]!=0){
                tree[tree[u].a[i]].fail=tree[tree[u].fail].a[i];
                q.push(tree[u].a[i]);
            }else{
                tree[u].a[i]=tree[tree[u].fail].a[i];
            }
        }
    }
    return;
}
void check(string s){
    int now=0;
    int len=s.length();
    for(int i=0;i<len;i++){
        int t=s[i]-97;
        now=tree[now].a[t];
        for(int j=now;j;j=tree[j].fail){
            re[tree[j].ed].cont++;
        }
    }
    return;
}
inline void clean(int i){
    memset(tree[i].a,0,sizeof(tree[i].a));
    tree[i].fail=0;
    tree[i].ed=0;
    return;
}
int main(){
    int n=1;
    while(n!=0){
        cin>>n;
        if(n==0)break;
        for(int i=0;i<=cnt;i++){
            clean(i);
        }
        cnt=0;
        for(int i=1;i<=n;i++){
            cin>>s[i];
            re[i].cont=0;
            re[i].i=i;
            insert(s[i],i);
        }
        getfail();
        cin>>s[0];
        check(s[0]);
        sort(re+1,re+n+1,cmp);
        cout<<re[1].cont<<endl;
        cout<<s[re[1].i]<<endl;

        for(int i=2;i<=n;++i){
            if(re[i].cont==re[i-1].cont){
                cout<<s[re[i].i]<<endl; 
            }
            else break;
        }
    }
    return 0;
}

P3366 【模板】最小生成樹
https://www.luogu.org/problem/show?pid=3366

//kruskal
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
struct edge{
    int u;
    int v;
    int w;
}e[200001];
bool cmp(edge a,edge b){
    return a.w<b.w;
}
int fa[5001]={0};
int find(int a){
    if(fa[a]!=a)fa[a]=find(fa[a]);
    return fa[a];
}
bool unionn(int a,int b){
    int k=find(a);
    int p=find(b);
    if(k!=p){
        fa[p]=k;
        return 1;
    }
    return 0;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    }
    sort(e+1,e+1+m,cmp);
    int cnt=0,sum=0;
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=m;i++){
        if(unionn(e[i].u,e[i].v)){
            cnt++;
            sum+=e[i].w;
        }
        if(cnt==n-1)break;
    }
    int pan=0;
    for(int i=1;i<=n;i++)if(fa[i]==i)pan++;
    if(pan==1)printf("%d",sum);
    else printf("orz");
    return 0;
}

寒假考試題
質數
結果碰到了然後重新寫了一波
發現這種寫法比較好理解
那麼存一下把

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
int a[1001];
int on[1001]={0};
int n,m;
int sfk[1001]={0};
int suan=0;
void gredy(int maxn){
    if(maxn>m)return;
    for(int i=maxn;i<=m;i++){
        int ok=0,mie=0;
        for(int j=a[i];j<=n;j++){
            if(j%a[i]==0){
                if(on[j]==1){
                    mie++;
                }
                if(on[j]==0){
                    ok++;
                }
            }
        }
        if(ok>mie){
            for(int j=a[i];j<=n;j++){
                if(j%a[i]==0){
                    on[j]=1-on[j];
                }
            }   
        }
    }
    return;
}
void dfs(int i,int maxn){
    if(i>maxn){
        memset(on,0,sizeof(on));
        for(int j=1;j<=maxn;j++){
            if(sfk[j]==1){
                for(int k=a[j];k<=n;k++){
                    if(k%a[j]==0){
                        on[k]=1-on[k];
                    }
                }
            }
        }
        gredy(maxn+1);
        int ans=0;
        for(int i=1;i<=n;i++){
            if(on[i]==1)ans++;
        }
        if(ans>suan){
            suan=ans;
        }
    }else{
        for(int j=1;j>=0;j--){
            sfk[i]=j;
            dfs(i+1,maxn);
        }
    }
    return;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        suan=0;
        memset(sfk,0,sizeof(sfk));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+m+1);
        int maxn=min(m,11);
        dfs(1,maxn);
        printf("%d\n",suan);
    }
    return 0;
}

記一道題
51nod 1459 迷宮遊戲
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1459
得等我複習dji才能寫了……暴力被卡時了
TLE代碼如下

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=501;
const int INF=2147483630;
int sc[maxn];
struct{
    int to;
    int next;
    int w;
}edge[maxn*2];
int cnt=0,head[maxn]={0};
void add(int u,int v,int w){
    cnt++;
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
    return;
}
bool vis[maxn]={0};
int mint=INF,maxw=0;
void dfs(int u,int ed,int t,int sum){
    if(u==ed){
        if(mint>t){
            mint=t;
            maxw=sum;
        }else if(mint==t){
            if(maxw<sum){
                maxw=sum;
            }
        }
        return;
    }
    if(t>mint)return;
    vis[u]=1;
    for(int i=head[u];i;i=edge[i].next){
        int v=edge[i].to;
        int w=edge[i].w;
        if(vis[v]==0){
            dfs(v,ed,t+w,sum+sc[v]);
            vis[v]=0;
        }
    }
    return;
}
int main(){
    int n,m,st,ed;
    scanf("%d%d%d%d",&n,&m,&st,&ed);
    for(int i=0;i<n;i++){
        scanf("%d",&sc[i]);
    }
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    dfs(st,ed,0,sc[st]);
    printf("%d %d",mint,maxw);
    return 0;
}

hdu 5188
一道需要動腦子的01揹包。
於是做一半就去看題解了……gg。
能力還不夠啊。
空間最初開小了。
然後就直接看題解的空間開多大就開多大了。

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct node{
    int t;
    int v;
    int l;
}a[31];
bool cmp(node b,node c){
    if((b.l-b.t)<(c.l-c.t))return 1;
    return 0;
}
int f[3000005]={0};//表示時間用量 
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        memset(f,0,sizeof(f));
        int w,ans=0,sum=0,maxn=0;
        scanf("%d",&w);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&a[i].t,&a[i].v,&a[i].l);
            sum+=a[i].v;//分數總和 
            ans+=a[i].t;//時間總和 
            maxn=max(maxn,a[i].l);//最遲交題時間 
        }
        if(w>sum){//分數和不夠要求 
            printf("zhx is naive!\n");  
            continue; 
        }
        sort(a+1,a+n+1,cmp);
        maxn=max(maxn,ans);//與時間總和再比 
        for(int i=1;i<=n;i++){
            for(int j=maxn;j>=a[i].l;j--){//該題可答時間段 
                if(j>=a[i].t){//該題是否合法 
                    f[j]=max(f[j],f[j-a[i].t]+a[i].v);
                }
            }
        }
        bool ok=0;
        for(int i=0;i<=maxn;i++){
            if(f[i]>=w){
                printf("%d\n",i);  
                ok=1;  
                break;
            }
        }
        if(ok==0){
            printf("zhx is naive!\n");  
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章