• NOIP2017解题报告


    啊不小心点发布了,懒得删了就这样吧,虽然还没写完,也不打算写了大概。

    d1t1

    结论题 没什么好说的

    d1t2

    模拟 没什么好说的

    d1t3

    70分算法其实比较好想。

    没有0边,就跑最短路,然后按dis从小到大转移。

    场上最后十分钟才发现单向边,就没时间考虑0边,并且相当于傻逼一样排了个序,水了60;

    肯定不能直接排序呀  n*k*log爆了啊,只把n个点按dis排序,然后先枚举一个k即可,肯定是从k小的转移到大的。

    然后0边重新建图,拓扑排序,看环上有没有可行解,有就输出-1。否则把拓扑序作为第二关键字排序,转移即可。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<ctime>
    #include<cmath>
    const int N=100005;
    const int M=200005;
    typedef long long LL;
    using namespace std;
    
    int T,n,m,k,p;
    LL dp[N][51];
    
    template<typename T> void read(T &x) {
    	char ch=getchar(); x=0; T f=1;
    	while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    	if(ch=='-') f=-1,ch=getchar();
    	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int fir[N],nxt[M],to[M],val[M],ecnt;
    int fif[N],nxf[M],tf[M],vaf[M],ecnf;
    void add(int u,int v,int w) {
    	nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
    	nxf[++ecnf]=fif[v]; fif[v]=ecnf; tf[ecnf]=u; vaf[ecnf]=w;
    }
     
    int fi[N],nx[M],tt[M],in[N],ec;
    void Add(int u,int v) {
    	nx[++ec]=fi[u]; fi[u]=ec; tt[ec]=v; in[v]++;
    }
    
    queue<int>que;
    int ds[N],dt[N],vis[N],tps[N];
    void spfa(int s,int d[],int fir[],int nxt[],int to[],int val[]) {
    	d[s]=0;
    	vis[s]=1;
    	que.push(s);
    	while(!que.empty()) {
    		int x=que.front();
    		que.pop();
    		vis[x]=0;
    		for(int i=fir[x];i;i=nxt[i]) 
    			if(d[to[i]]>d[x]+val[i]) {
    				d[to[i]]=d[x]+val[i];
    				if(!vis[to[i]]) {
    					vis[to[i]]=1;
    					que.push(to[i]);
    				}
    			}
    	}
    }
    
    int tpsort() {
    	for(int i=1;i<=n;i++) if(!in[i]) que.push(i);
    	int idd=0;
    	while(!que.empty()) {
    		int x=que.front();
    		que.pop();
    		tps[x]=++idd;
    		for(int i=fi[x];i;i=nx[i]) {
    			if(!(--in[tt[i]]))
    				que.push(tt[i]);
    		} 
    	} 
    	for(int i=1;i<=n;i++) 
    		if(in[i]&&ds[i]+dt[i]<=ds[n]+k) 
    			return 1;
    	return 0;
    }
    
    struct node{
    	int x;
    	friend bool operator <(const node &A,const node &B) {
    		return ds[A.x]==ds[B.x]?tps[A.x]<tps[B.x]:ds[A.x]<ds[B.x];
    	}
    }po[N*50];
    
    void clear() {
    	ecnt=ec=ecnf=0;
    	memset(dt,127,sizeof(dt));
    	memset(ds,127,sizeof(ds));
    	memset(fi,0,sizeof(fir)); 
    	memset(fir,0,sizeof(fir));
    	memset(fif,0,sizeof(fif));
    	memset(in,0,sizeof(in));
    	memset(tps,0,sizeof(tps));
    	memset(dp,0,sizeof(dp));
    }
    
    void work() {
    	spfa(1,ds,fir,nxt,to,val); 
    	spfa(n,dt,fif,nxf,tf,vaf);
    	if(tpsort()) printf("-1
    ");
    	else {
    		int tot=0;
    		for(int i=1;i<=n;i++) 
    			po[++tot].x=i;
    		dp[1][0]=1;
    		sort(po+1,po+tot+1);
    		for(int y=0;y<=k;y++) {
    		for(int o=1;o<=tot;o++) {
    			int x=po[o].x;
    			for(int i=fir[x];i;i=nxt[i]) 
    				if((LL)ds[x]+y+val[i]+dt[to[i]]<=ds[n]+k) {
    					(dp[to[i]][ds[x]+y+val[i]-ds[to[i]]]+=dp[x][y])%=p;
    				}
    		}
    		}
    		LL ans=0;
    		for(int i=0;i<=k;i++) (ans+=dp[n][i])%=p;
    		printf("%lld
    ",ans);
    	}
    }
    
    void init() {
    	read(T);
    	while(T--) {
    		clear();
    		read(n);
    		read(m);
    		read(k);
    		read(p);
    		for(int i=1;i<=m;i++) {
    			int u,v,w;
    			read(u); read(v); read(w);
    			if(!w) Add(u,v);
    			add(u,v,w);
    		}
    		work();
    	}
    }
    
    #define DEBUG
    int main() {
    #ifdef DEBUG
    	freopen("park.in","r",stdin);
    	freopen("park.out","w",stdout);
    #endif
    	init();
    	return 0;
    }
    

      

    d2t1

    并查集

    之前在长一考了一道有点像的二维的用并查集这样搞可以水80;

    d2t2

    一眼状压,然后不会。

    推了半个小时prufer数列,并没有什么用。

    自己对dp的理解还是太粗浅了。

    一个可做的方法是,枚举层数,枚举状态,枚举补集,暴力转移。

    你觉得十分不科学,然而事实是这样是可以得出正确答案的。

    几个事。

    1。不一定全部的状态或者转移都是最优的,只要最终可以达到最优解即可。

    2。注意细节,如果层数枚举到12然后空间只开13你不就越界了嘛。。

    3。省略一些不用的转移,比如dp==inf时直接略过,不然会死亡tle。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<ctime>
    #include<cmath>
    #define inf 0x7fffffff
    typedef long long LL;
    using namespace std;
    const int N=13;
    int n,m,dis[N][N];
    LL dp[N][1<<N]; 
    
    template<typename T> void read(T &x) {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int q1[N],q2[N],t1,t2;
    LL cal(int s,int t) {
        t1=t2=0;
        LL res=0;
        for(int i=1;i<=n;i++) {
            if(s&(1<<(i-1))) q1[++t1]=i;
            if(t&(1<<(i-1))) q2[++t2]=i;
        }
        for(int i=1;i<=t2;i++) {
            int tp=1e9;
            for(int j=1;j<=t1;j++) 
                tp=min(tp,dis[q2[i]][q1[j]]);
            res+=tp;
        } 
        return res;
    }
    
    void work() {
        int nn=(1<<n)-1; 
        LL ans=1e9;
        for(int i=0;i<=n;i++) 
            for(int j=0;j<=nn;j++)
                dp[i][j]=inf;
        for(int i=1;i<=n;i++) dp[1][1<<(i-1)]=0;
        for(int i=1;i<n;i++) {
            for(int s=1;s<=nn;s++) if(dp[i][s]!=inf){
                int bj=nn^s;
                for(int vv=bj;vv;vv=(vv-1)&bj) 
                    dp[i+1][s|vv]=min(dp[i+1][s|vv],dp[i][s]+i*cal(s,vv));
            }
            ans=min(ans,dp[i][nn]);
        }
        ans=min(ans,dp[n][nn]);
        printf("%lld
    ",ans);
    }
    
    void init() {
        read(n);
        read(m);
        memset(dis,127/3,sizeof(dis));
        for(int i=1;i<=m;i++) {
            int u,v,w;
            read(u); read(v); read(w);
            dis[u][v]=min(dis[u][v],w);
            dis[v][u]=dis[u][v];
        }
    }
    
    int main() {
    #ifdef DEBUG
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    #endif
        init();
        work();
        return 0;
    }
    

      

    d2t3列队

    --------------------2018-10-13upd------------------------

    拿splay打了这题

    WA了一面的提交记录,连个splay都打不陈展,真是菜哭自己

      1 //Achen
      2 #include<bits/stdc++.h>
      3 #define For(i,a,b) for(int i=(a);i<=(b);i++) 
      4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
      5 #define Formylove return 0
      6 const int N=3e6+7;
      7 typedef long long LL;
      8 typedef double db;
      9 using namespace std;
     10 int n,m,q;
     11 
     12 template<typename T>void read(T &x) {
     13     char ch=getchar(); T f=1; x=0;
     14     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
     15     if(ch=='-') f=-1,ch=getchar();
     16     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
     17 }
     18 
     19 int rt[N];
     20 int tot,ch[N][2],p[N];
     21 LL l[N],r[N],sz[N];
     22 #define lc ch[x][0]
     23 #define rc ch[x][1]
     24 void upd(int x) { sz[x]=sz[lc]+sz[rc]+(r[x]-l[x]+1); }
     25 
     26 void rotate(int x) {
     27     int y=p[x],z=p[y],l=(x==ch[y][1]),r=(l^1);
     28     if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
     29     ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
     30     ch[x][r]=y; p[y]=x;
     31     upd(y); upd(x);
     32 }
     33 
     34 void splay(int &rt,int x) {
     35     for(;p[x];rotate(x)) {
     36         int y=p[x],z=p[y];
     37         if(z) ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
     38     }
     39     rt=x;
     40 }
     41 
     42 int find(int &rt,int k) {
     43     int x=rt;
     44     for(;;) {
     45         if(sz[lc]+1<=k&&sz[lc]+r[x]-l[x]+1>=k) { k-=sz[lc]; break; }
     46         if(sz[lc]+r[x]-l[x]+1<k) { k-=sz[lc]+r[x]-l[x]+1; x=rc; }
     47         else x=lc;
     48     }
     49     splay(rt,x);
     50     if(r[x]!=l[x]) {
     51         if(k==1||k==r[x]-l[x]+1) {
     52             if(k==1) { l[++tot]=l[x]; r[tot]=l[x]; l[x]++; }
     53             else { l[++tot]=r[x]; r[tot]=r[x]; r[x]--; }
     54         }
     55         else {
     56             l[++tot]=l[x]+k; r[tot]=r[x]; r[x]=l[x]+k-2;
     57             ch[tot][1]=ch[x][1]; if(ch[x][1]) p[ch[x][1]]=tot;
     58             ch[x][1]=tot; p[tot]=x; 
     59             upd(tot); upd(x);
     60             l[++tot]=l[x]+k-1; r[tot]=l[tot]; 
     61         }
     62         upd(tot);
     63         return tot;
     64     }
     65     else {
     66         if(!lc) { rt=rc; p[rc]=0; }
     67         else if(!rc) { rt=lc; p[lc]=0; }
     68         else {
     69             int a=lc,b=rc;
     70             p[lc]=p[rc]=0; 
     71             rt=a; while(ch[a][1]) a=ch[a][1];
     72             splay(rt,a); 
     73             ch[a][1]=b; p[b]=a;
     74             upd(a); 
     75         }
     76         lc=rc=0; upd(x);
     77         return x;
     78     }
     79 }
     80 
     81 void insert(int &rt,int y) {
     82     if(!rt) { rt=y; return; }
     83     int x=rt;
     84     while(rc) x=rc;
     85     splay(rt,x);
     86     rc=y; p[y]=x; upd(x);
     87 }
     88 
     89 //#define ANS
     90 int main() {
     91 #ifdef ANS
     92     freopen("1.in","r",stdin);
     93     freopen("1.out","w",stdout);
     94 #endif
     95     read(n); read(m); read(q);
     96     For(i,1,n) {
     97         rt[i]=++tot;
     98         l[tot]=((LL)i-1)*m+1; r[tot]=(LL)i*m-1;
     99         upd(tot);
    100     }
    101     For(i,1,n) {
    102         int x=++tot;
    103         l[tot]=r[tot]=(LL)i*m;
    104         upd(tot);
    105         insert(rt[n+1],x);
    106     }
    107     For(cas,1,q) {
    108         int x,y;
    109         read(x); read(y);
    110         if(y==m) {
    111             int t=find(rt[n+1],x);
    112             printf("%lld
    ",l[t]);
    113             insert(rt[n+1],t);
    114         }
    115         else {
    116             int t1=find(rt[x],y);
    117             int t2=find(rt[n+1],x);
    118             printf("%lld
    ",l[t1]);
    119             insert(rt[x],t2);
    120             insert(rt[n+1],t1);            
    121         }
    122     }
    123     Formylove;
    124 }
    View Code
  • 相关阅读:
    Day09 约束
    Day08 数据处理
    Day07 创建和管理表
    Day06 子查询
    Appium学习_01(连接、apppackage名查询、appactivity名查询)
    我的读书方法
    Python自动化学习记录
    FineReport帆软报表学习积累
    ERP企业资源管理 详解
    Centos7学习记录
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7921808.html
Copyright © 2020-2023  润新知