寒假学习记录D27

题目描述

给定一个 nn 个点的有向图,请求出图中是否存在从顶点 11 出发能到达的负环。

负环的定义是:一条边权之和为负数的回路。

输入格式

本题单测试点有多组测试数据

输入的第一行是一个整数 TT,表示测试数据的组数。对于每组数据的格式如下:

第一行有两个整数,分别表示图的点数 nn 和接下来给出边信息的条数 mm。

接下来 mm 行,每行三个整数 u, v, wu,v,w。

  • 若 w \geq 0w≥0,则表示存在一条从 uu 至 vv 边权为 ww 的边,还存在一条从 vv 至 uu 边权为 ww 的边。
  • 若 w < 0w<0,则只表示存在一条从 uu 至 vv 边权为 ww 的边。

输出格式

对于每组数据,输出一行一个字符串,若所求负环存在,则输出 YES,否则输出 NO

输入输出样例

输入 

2
3 4
1 2 2
1 3 4
2 3 1
3 1 -3
3 3
1 2 3
2 3 4
3 1 -8

输出 

NO
YES

说明/提示

数据规模与约定

对于全部的测试点,保证:

  • 1 \leq n \leq 2 \times 10^31≤n≤2×103,1 \leq m \leq 3 \times 10^31≤m≤3×103。
  • 1 \leq u, v \leq n1≤u,v≤n,-10^4 \leq w \leq 10^4−104≤w≤104。
  • 1 \leq T \leq 101≤T≤10。

提示

请注意,mm 不是图的边数。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
int st[N],cnt[N],dist[N],t,n,m,p[N];
int h[N],e[N],w[N],ne[N],idx;
queue<int>q,temp;
void init()
{
    q=temp;
	idx=0;
	memset(h,-1,sizeof h);
	memset(st,0,sizeof st);
	memset(cnt,0,sizeof cnt);
	memset(dist,0x3f,sizeof dist);
	for(int i=1;i<=n;i++) p[i]=i;
}
int find(int x)
{
    if(x!=p[x]) p[x]=find(p[x]);
    return p[x];
}
void add(int a,int b,int c) {e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;}
bool spfa()
{
    q.push(1),st[1]=1,dist[1]=0;
	while(q.size())
	{
		int u=q.front(); q.pop();
		st[u]=false;
		for(int i=h[u];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(dist[j]>dist[u]+w[i])
			{
				dist[j]=dist[u]+w[i];
				cnt[j]=cnt[u]+1;
				if(cnt[j]>=n) return true;
				if(!st[j]) q.push(j),st[j]=1;
			}
		}
	}
	return false;
}
int main(void)
{
    cin>>t;
	while(t--)
	{
		cin>>n>>m;
		init();
		for(int i=0;i<m;i++)
		{
			int a,b,c; cin>>a>>b>>c;
			if(c>=0) add(a,b,c),add(b,a,c);
			else add(a,b,c);
		}
		if(spfa()) puts("YES");
		else puts("NO");
	}
	return 0;
}

 

题目描述

给出两个字符串 s_1s1​ 和 s_2s2​,若 s_1s1​ 的区间 [l, r][l,r] 子串与 s_2s2​ 完全相同,则称 s_2s2​ 在 s_1s1​ 中出现了,其出现位置为 ll。
现在请你求出 s_2s2​ 在 s_1s1​ 中所有出现的位置。

定义一个字符串 ss 的 border 为 ss 的一个非 ss 本身的子串 tt,满足 tt 既是 ss 的前缀,又是 ss 的后缀。
对于 s_2s2​,你还需要求出对于其每个前缀 s's′ 的最长 border t't′ 的长度。

输入格式

第一行为一个字符串,即为 s_1s1​。
第二行为一个字符串,即为 s_2s2​。

输出格式

首先输出若干行,每行一个整数,按从小到大的顺序输出 s_2s2​ 在 s_1s1​ 中出现的位置。
最后一行输出 |s_2|∣s2​∣ 个整数,第 ii 个整数表示 s_2s2​ 的长度为 ii 的前缀的最长 border 长度。

输入输出样例

输入 

ABABABC
ABA

输出 

1
3
0 0 1 

说明/提示

样例 1 解释

对于 s_2s2​ 长度为 33 的前缀 ABA,字符串 A 既是其后缀也是其前缀,且是最长的,因此最长 border 长度为 11。

数据规模与约定

本题采用多测试点捆绑测试,共有 3 个子任务

  • Subtask 1(30 points):|s_1| \leq 15∣s1​∣≤15,|s_2| \leq 5∣s2​∣≤5。
  • Subtask 2(40 points):|s_1| \leq 10^4∣s1​∣≤104,|s_2| \leq 10^2∣s2​∣≤102。
  • Subtask 3(30 points):无特殊约定。

对于全部的测试点,保证 1 \leq |s_1|,|s_2| \leq 10^61≤∣s1​∣,∣s2​∣≤106,s_1, s_2s1​,s2​ 中均只含大写英文字母

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>

using namespace std;

int next[1000005];
string s,p;
void getnext(string s)
{
        int j=0;//初始化
        next[0]=0;
        for(int i=1;i<s.length();i++)
        {
             while(j>0&&s[i]!=s[j])  j=next[j-1];//向前移一位//处理前后缀不相同
             if(s[j]==s[i])  j++;//向后移一位//处理前后缀相同
             next[i]=j;//更新next 数组
        }
}
void kmp(string s,string p)
{
    int j=0;//j可以看做表示当前已经匹配完的模式串的最后一位的位置
    for(int i=0;i<s.length();i++)
    {
        while(j>0&&p[j]!=s[i]) j=next[j-1]; //如果失配 ,那么就向回跳
        if (p[j]==s[i]) j++;//匹配成功,向后继续
        if (j==p.length())
        {
            cout<<i+1-p.length()+1<<endl;
            j=next[j-1];//继续匹配
        }
    }
    return ;
}
int main()
{
    cin>>s>>p;
    getnext(p);
    kmp(s,p);
    for(int i=0;i<p.length();i++)
    {
        cout<<next[i]<<' ';
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值