临时代码储存

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章