10.6 解题报告

T1

考场用时:\(30\) s
期望得分:\(100\) pts
实际得分:\(100\) pts
这题是人尽皆知的结论题:\(ab-a-b\),代码不贴了,没意义。

T2

考场用时:\(1\) h
期望得分:\(100\) pts
实际得分:\(100\) pts
一道不算太大也不算太小的模拟,注意最好把所有询问离线下来再处理,不然 break continue 什么的很容易出锅。

#include<bits/stdc++.h>
#define ll long long
#define int long long
//#define ull unsigned long long
#define lc(k) k<<1
#define rc(k) k<<1|1
#define lb lower_bound
#define orz cout<<"gzn ak ioi\n"
const int MAX=1e6+10;
const int MOD=1e9+7;
using namespace std;
inline char readchar() {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
	int res = 0, f = 0;
	char ch = readchar();
	for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
	for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
	return f ? -res : res;
}
inline void write(int x) {
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
char s[100],fr[100],to[100];
int T,L,kans,ans;
int stc[MAX],sc=0,zimu[MAX];
bool vis[MAX];
signed main(){
    T=read();
    while(T--){
        sc=0;kans=0,ans=0;
        memset(vis,false,sizeof vis);
        L=read();cin>>s+1;
        if(s[3]=='1') kans=0;
        else{
            int len=strlen(s+1);
            for(int i=1;i<=len;++i) 
                if(s[i]>='0'&& s[i]<='9') 
                    kans=kans*10+s[i]-'0';
        }
        bool Flag=0;
        for(int i=1;i<=L;++i) {
            char opt;cin>>opt;
            if(opt=='F'){
                ++sc;char g;
                cin>>g;
                if(vis[g]) Flag=1;
                vis[g]=1;zimu[sc]=g;
                cin>>fr+1>>to+1;
                if(fr[1]=='n'){
                    if(to[1]=='n') stc[sc]=0;
                    else stc[sc]=2;
                }
				else{
                    if(to[1]=='n') stc[sc]=1; 
                    else{
                        int len1=strlen(fr+1),len2=strlen(to+1);
                        int sum1=0, sum2=0;
                        for(int j=1;j<=len1;++j) sum1=sum1*10+fr[j]-'0';
                        for(int j=1;j<=len2;++j) sum2=sum2*10+to[j]-'0';
                        if(sum1>sum2) stc[sc]=2;
                        else stc[sc]=0;
                    }
                }
            }
			else{
                vis[zimu[sc]]=0;--sc;
                if(sc<0) Flag=1;
            }
            int cnt=0;
            for(int j=1;j<=sc;++j) {
                if(stc[j]==2) break;
                cnt += stc[j];
            }
            ans=max(ans, cnt);
        }
        if(sc) Flag=true;
        if(Flag) puts("ERR");
        else if(ans==kans) puts("Yes");
        else puts("No");
    }
	return 0;
}

T3

考场用时:\(2\) h
期望得分:\(70\) pts
实际得分:\(0\) pts
这题写了无 \(0\) 权边的 \(70\),但没有注意 dp 的顺序,应该先更新从 \(1\) 到达的最短距离更小的点。

#include<bits/stdc++.h>
#define ll long long
//#define int long long
//#define ull unsigned long long
#define lc(k) k<<1
#define rc(k) k<<1|1
#define lb lower_bound
#define orz cout<<"gzn ak ioi\n"
const int MAX=2010;
int MOD;
using namespace std;
inline char readchar() {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
#define readchar getchar
	int res = 0, f = 0;
	char ch = readchar();
	for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
	for(; isdigit(ch);ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
	return f ? -res : res;
}
inline void write(int x) {
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
/*
dp[i][j] 表示到达点i,总距离是j的方案数
只需从dis[i]转移到dis[i]+K
只要某个size>1的强联通分量边权和为0
且过这个点的最短路符合要求,则直接输出-1 
复杂度O(nK)
*/
int vis[MAX],dis1[MAX],disn[MAX];
int head1[MAX],head2[MAX],cnt1,cnt2;
struct node{int u,v,w,net;}e1[MAX],e2[MAX];
void add1(int u,int v,int w){
	e1[++cnt1]=(node){u,v,w,head1[u]};
	head1[u]=cnt1;
	return ;
}
void add2(int u,int v,int w){
	e2[++cnt2]=(node){u,v,w,head2[u]};
	head2[u]=cnt2;
	return ;
}
int n,m,K,scc[MAX],scc_sum,siz[MAX],w[MAX];
priority_queue<pair<int,int> > q;
#define mk make_pair
#define id second
void dij(int u,int dis[],int head[],node e[]){
	memset(vis,0,sizeof vis);
	for(int i=1;i<=n;i++) dis[i]=1e9;
	dis[u]=0;
	q.push(mk(0,u));
	while(!q.empty()){
		pair<int,int> f=q.top();q.pop();
		if(vis[f.id]) continue;
		vis[f.id]=1;
		for(int i=head[f.id];i;i=e[i].net){
			int v=e[i].v;
			if(dis[f.id]+e[i].w<dis[v]){
				dis[v]=dis[f.id]+e[i].w;
				q.push(mk(-dis[v],v)); 
			}
		}
	}
	return ;
}
int dfn[MAX],stc[MAX],tp,tot,low[MAX];
void tarjan(int u){
	vis[u]=1;stc[++tp]=u;
	low[u]=dfn[u]=++tot;
	for(int i=head1[u];i;i=e1[i].net){
		int v=e1[i].v;
		if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
		else if(vis[v]) low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u]){
		++scc_sum;
		siz[scc_sum]=1;
		scc[u]=scc_sum;
		vis[u]=0;
		while(stc[tp]!=u){
			scc[stc[tp]]=scc_sum;
			siz[scc_sum]++;
			vis[stc[tp]]=0;
			tp--;
		}
		tp--;
	}
	return ;
}
int rd[MAX],dp[MAX][100000],dis[MAX];
queue<int> Q;
bool topo(){
	for(int i=1;i<=scc_sum;i++)
		if(!rd[i]) Q.push(i);
	dp[scc[1]][0]=1;
	while(!Q.empty()){
		int f=Q.front();Q.pop();
//		cout<<f<<endl;
		if(siz[f]>1&&!w[f]) return 0;
		for(int i=head2[f];i;i=e2[i].net){
			int v=e2[i].v;
			rd[v]--;if(!rd[v]) Q.push(v);
			for(int j=e2[i].w;j<=10000;j++){
				dp[v][j]=(dp[f][j-e2[i].w]+dp[v][j])%MOD;
				if(siz[v]>1) dp[v][j+w[v]]=(dp[v][j+w[v]]+dp[v][j])%MOD;
			}
		}
	}
	return 1;
}
signed main(){
	int T=read();
	while(T--){
		cnt1=cnt2=0;
		n=read(),m=read(),K=read(),MOD=read();
		for(int i=1;i<=n;i++) head1[i]=head2[i]=0;
		for(int i=1;i<=n;i++) scc[i]=vis[i]=0;
		for(int i=1;i<=n;i++) dfn[i]=low[i]=0;
		for(int i=1;i<=n;i++) stc[i]=0;
		tp=tot=scc_sum=0;
		for(int i=1;i<=m;i++){
			int u=read(),v=read(),w=read();
			add1(u,v,w);add2(v,u,w);
		}
		dij(1,dis1,head1,e1);
		dij(n,disn,head2,e2);
		memset(vis,0,sizeof vis);
		for(int i=1;i<=n;i++)
			if(!dfn[i]) tarjan(i);
//		for(int i=1;i<=n;i++) cout<<scc[i]<<" ";
		for(int i=1;i<=n;i++) head2[i]=0,dis[scc[i]]=dis1[i];
		cnt2=0;
		for(int i=1;i<=cnt1;i++){
			int u=scc[e1[i].u],v=scc[e1[i].v],W=e1[i].w;
			if(u!=v) add2(u,v,W),rd[v]++/*,cout<<u<<" "<<v<<" "<<W<<endl*/;
			else{
				w[u]+=e1[i].w;
				dis[u]=min(dis1[e1[i].u]+disn[e1[i].u],dis[u]);
			}
		}
		if(!topo()) puts("-1");
		else{
			int ans=0;
			for(int i=0;i<=K;i++) ans=(ans+dp[scc[n]][dis1[n]+i])%MOD;
			write(ans);putchar('\n');
		}
	}
	return 0;
}
/*

1
5 7 2 10
1 2 1
2 4 0
4 5 2
2 3 2
3 4 1
3 5 2
1 5 3

*/
posted @ 2022-11-06 22:31  wapmhac  阅读(14)  评论(0编辑  收藏  举报